js改變this指向的方法:call apply bind
阿新 • • 發佈:2018-11-10
- 在函式中使用this
function foo(c, d) {
return this.a + this.b + c + d
}
global.a = 3
global.b = 4
// foo執行時,this沒有明確的指向,預設指向全域性物件global
// nodejs中是global,browser中是window
foo(3, 4) // 14
call apply bind是函式Function原型的方法,所有函式繼承自Function.prototype
foo.call === Function.prototype.call // true
foo.apply === Function.prototype.apply // true
foo.bind === Function.prototype.bind // true
- call() apply()
this會暫時繫結call和apply的第一個引數。傳遞null和undefined,this將繫結到全域性物件global。後面的引數,call接收的是引數列表,apply接收的是引數陣列。
let o = {a: 1, b: 2}
// foo.call(obj, ...[arguments])
foo.call(o, 3, 4) // 10
foo.call(null , 3, 4) // 14
foo.call(undefined, 3, 4) // 14
foo.call(global, 3, 4) // 14
// foo.apply(obj, [arguments])
foo.apply(o, [3, 4]) // 10
foo.apply(null, [3, 4]) // 14
call apply bind的第一個引數如果不是物件,會先呼叫內部的ToObject方法轉換成物件。
function foo(){
return typeof this
}
// 分別呼叫Number和String的constructor
foo.call(1) // object, new Number(1)
foo.call('a') // object, new String('a')
es6支援使用擴充套件運算子,一些情況下可以不再使用call、apply、bind。
// 求陣列最大值
let arr = [4, 3, 2, 1]
Math.max.call(null, ...arr) // 4
Math.max.apply(null, arr) // 4
Math.max(...arr) // 4
// 資料型別判斷
Object.prototype.toString.call(1) // [object Number]
Object.prototype.toString.call('a') // [object String]
new (Date.bind.apply(Date, [null, 2018, 5, 26]))
new Date(...[2018, 5, 26])
- bind()
函式的bind方法會建立一個新的函式,新函式中的this會永久繫結bind傳入的第一個引數,其他引數初始化後也不會改變。
let o = {a: 1, b: 2}
let f1 = foo.bind(o, 3, 4)
let f2 = f1.bind(null, 10, 10)
f1() // 10
f2() // 10, 並沒有繫結global, 引數c和d的值也沒有改變
f1 === f2 // false, f1和f2並不相等
f1.call(null, 10, 10) // 10, 在f1上使用call仍然沒有改變