js改变this指向的方法(call apply bind)

  • 在函数中使用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()
【js改变this指向的方法(call apply 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仍然没有改变

    推荐阅读