- 在函数中使用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仍然没有改变