function f() {
console.log(this);
}
let f1 = f.bind(1).bind(2)
f1()
複製代碼
解析:javascript
Function.prototype.bind = function (thisArg) {
var _this = this
return function () {
_this.apply(thisArg)
}
}
複製代碼
bind 原理:java
bind的原理, bind的做用是永久改變一個函數執行過程當中的this,它的基本實現
bind的執行不會當即執行須要改變this指向的函數
bind執行後返回一個新函數
新函數調用會間接調用源函數來實現源函數的執行
函數執行過程當中經過apply(apply、call)把this指向thisArg 閉包:
內層函數能夠訪問外層數據 內層:return 後面的函數 外層:bind函數阻止垃圾回收,
因此即便bind已經執行完成了,可是由於return的函數被外部引用,
因此bind中的thisArg並無被回收,
這樣後續不管何時調用return出去的函數都能訪問到thisArg
複製代碼
因此:閉包
function f() {
console.log(this);
}
let f1 = f.bind(1).bind(2);
f1();
// 其實能夠當作下面的調用
let temp = f.bind(1);
let f1 = temp.bind(2);
f1();
首先 temp 是 f.bind(1) 的結果
temp = function(1) {
// 這裏的 thisArg = 1
function() {
f.apply(1);
}
}
//也就是temp調用的時候接收了一個1的參數,而後間接的調用了f,並把f的this指向了temp的參數1
//而後 let f1 = temp.bind(2) 執行之後 f1 代碼
f1 = function(2) {
// 這裏的 thisArg = 2
function() {
temp.apply(2);
}
}
// f1調用的時候接收了一個2的參數,而後間接的調用了temp,並把temp的this指向了2
複製代碼
其實這裏特別注意的是其實f1調用了temp並確實改了temp的this爲2,可是這裏是沒有調用最開始的f的,而是temp.apply(2)的時候再去調用的f.apply(2),因此不管中間有多少層bind,最後那個f調用永遠都是最開始的1app
let temp = f.bind(1);
let f1 = temp.bind(2);
let f2 = f1.bind(3);
let f3 = f2.bind(4);
let f4 = f3.bind(5);
f4();
f4() => f3.apply(5) => f2.apply(4) => f1.apply(3) => temp.apply(2)=>f.apply(1)
複製代碼
就是bind一次包一層函數,每一次都有本身的this指向,最後一次執行的也就是最開始bind的纔會執行初始綁定的函數,改變它的this.函數
function f() {
console.log(typeof this);
}
let f1 = f.bind(1).bind(2)
let val = f1() // object
複製代碼
this
永遠必須是個 對象,不能是其餘類型,雖然不能直接賦值,可是能夠經過call
、apply
、bind
內部改變 this
,可是爲了確保 this
爲對象類型,若是賦給他的值是非對象的,則會轉成對象post
解析:ui
function f() {
console.log(typeof this, this);
}
f.call(0)
// object Number {0} 實際上是: new Number(0)
f.call('hello world')
// object String {"hello world"} 實際上是: new String('hello world')
f.call(true)
// object String {"hello world"} 實際上是: new Boolean(true)
f.call(null)
// object Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
f.call(undefined)
// object Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
複製代碼