谈论JavaScipt中call apply bind,我们当然首先需要探讨的就是this的指向问题了
在 ES5 中,其实 this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象(看完所有例子,有补充部分的特殊情况)
例1:默认绑定
根据刚刚的那句话“this永远指向最后调用它的那个对象”,我们看调用 thisIndex()的地方;,前面没有调用的对象那么就是全局对象 window,这就相当于是 window.thisIndex();注意,这里我们没有使用严格模式,如果使用严格模式的话,全局对象就是 undefined
例2:同上
例3:隐式绑定
这里打印 function的原因也是因为刚刚那句话“this 永远指向最后调用它的那个对象”,最后调用它的对象是对象 a,相当于window.a.fn()
例4:隐式丢失=》默认绑定
这里你可能会有疑问,为什么不是 function,这是因为虽然将 a 对象的 fn 方法赋值给变量 f 了,但是没有调用,记住“this永远指向最后调用它的那个对象”,由于刚刚的 f 并没有调用,所以 fn() 最后仍然是被 window 调用的,即window.f()
以上例子我们可以看出,this的指向并不是在创建的时候就可以确定的,在 es5 中,this永远指向最后调用它的那个对象
补充:important!!!
例5:绑定例外
嗯???为什么是18???其实把函数执行的位置捋清楚也是符合规则的。
首先,showAge函数定义在一个对象中,里面有个定时器setTimeout,定时器等待300毫秒后执行打印操作,这应该没问题。
然后,在外面执行obj.showAge(),所以showAge里的this指向obj。在定时器中,作为回调函数的callback只是单纯地在符合条件后执行了,那么,这里的callback函数是不是没有被谁打点调用,所以该函数的this应该指向全局对象window。所以打印的就是全局的age,等于18。
同时也可以得到一个普遍的结论:一般的回调函数(立即执行函数,return函数等)的this指向全局对象window
改变this 的指向的方法:
1.使用 ES6 的箭头函数:
箭头函数拥有词法作用域的this值(即不会新产生自己作用域下的this, arguments, super 和 new.target 等对象)
也就是说箭头函数本身不具有this,它会直接绑定到它的词法作用域内的this,也就是定义它时的作用域内的this值。所以试图使用apply,call等方法修改箭头函数的this是不会成功的,因为箭头函数自身没有this。
例1:
:
例2:
箭头函数this总是指向该函数定义生效时所在的对象
例3:
例4:
2. 使用 apply、call、bind,显式绑定
先简单说一下call apply bind 的作用和使用方法:
call apply 都是改变一个函数的this指向并执行该函数,区别是传参列表不同,call(obj, 参数1, 参数2, …) apply(obj, arguments)
bind是改变一个函数的this指向并返回一个新的函数,传参结合call和apply的,只接收第一次绑定的this
例1:模拟call方法自定义一个myCall代码:
例2:模拟bind方法自定义一个myBind代码:
3.new绑定
new绑定可以参考我的上一篇文章
结语:
默认绑定,隐式绑定,显式绑定,new绑定的this 绑定四条规则,实现过程还是得大家好好理解,希望有错误的地方大家多多指正,纯属个人理解。