版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37722811/article/details/84189257
1.查找调用点:函数被调用的位置
大多数浏览器(Google)都内置开发者工具,其中就包含JS调试器。为什么要找函数的调用点?因为函数在调用点的调用形式决定了this绑定。
function foo(something) {
//debugger;
console.log(this.a,something);
return this.a + something;
}
var obj = {
a: 2
};
var bar = function () {
return foo.apply(obj,arguments);
};
var b = bar(3);
2. this绑定规则
默认绑定:独立函数调用,即函数被一个直白的,毫无修饰的函数引用调用,例如foo(), foo的this关键字被绑定到window。
隐含绑定:对象方法调用,即函数被作为对象的一个方法调用,在调用点,函数必须是对象obj的一个成员方法;例如obj.foo( ), foo的this关键字被绑定到obj。
显式绑定:调用函数的call(),apply()方法,显示的传递thisArgs,例如foo.call(obj), foo的this关键字被绑定到obj, 与隐含绑定的区别是,显示绑定的环境对象obj可以不包含这个函数foo,即两者无任何关系,只是执行时obj作为环境对象传递给函数foo使用。
构造绑定:使用new关键字调用函数,函数的this关键字被绑定到当前构造的实例。
3. 硬绑定
硬绑定是显示绑定的变种,当一个对象的方法作为参数传递给另一个函数时,隐含的绑定会丢失,当然函数执行时的this绑定取决于函数被调用的形式,我们不知道这个回调函数foo在另一个函数内部setTimeout中是如何调用的(最终的调用形式),为了防止不确定的事情发生,我们完全可以将回调函数包装成一个硬绑定函数后再传到给setTimeout。如下图:
function foo(){
console.log(this.a);
}
var obj = {
a: 2
}
/*
将foo包装成bar函数,无论如何调用和回调,都只能改包装函数bar的this绑定,内层函数foo的绑定始终不变,
所以我们称之为硬绑定,即明确又坚定。
*/
var bar = function() {
//显示绑定
foo.call(obj);
}
//传递包装函数bar
setTimeout(bar,100);
//使用函数表达式包装bar函数
setTimeout( function () { foo.call(obj)},100)
4. 箭头函数
ES6新增了箭头函数,箭头函数不仅仅是函数表达式的简写,省去了枯燥无味的function关键字,它的this绑定机制不属于以上的任何一种,它实际上采用的是词法作用域规则,箭头函数的this关键字继承外层词法作用域的this指向。后续会详细探讨,敬请期待............