一文搞定JavaScript的this指向问题
Posted 忘忘碎斌bin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文搞定JavaScript的this指向问题相关的知识,希望对你有一定的参考价值。
一文搞定javascript的this指向问题
代码执行时this在内存中的位置
注意:
this的绑定是在代码执行时动态绑定上去的,与函数定义的位置是无关的,而与函数调用的方式和调用的位置有关。
this绑定规则
规则一:默认绑定(独立函数调用)
一个函数经过其他操作,函数直接被调用,并没有进行任何的对象关联
规则二:隐式绑定
通过某个对象发起的函数调用
规则三:显示绑定
明确的给函数指定上一个对象(手动指定)
规则四:new 绑定
JavaScript中的函数可以当做类的构造函数来使用,也就是使用new关键字。
使用new关键字调用函数时,会进行以下操作:
- 创建一个对象
- 修改创建对象的原型(prototype)指向
- 修改创建函数内的this指向
- 返回创建的对象
系统API中的this指向
- 定时器
- DOM事件
- 数组方法
多个绑定优先级的比较
结论: new绑定 > 显示绑定( apply | call | bind ) > 隐式绑定(对象.函数名()) > 默认绑定(独立函数调用)
1、默认绑定的优先级是最低的
2、显示绑定的优先级高于隐式绑定
var obj = {
name: "obj",
foo: function () {
console.log(this);
},
};
obj.foo(); // {name: 'obj', foo: ƒ}
// 1、call/apply的显示绑定高于隐式绑定
obj.foo.call("fzb"); // String {'fzb'}
obj.foo.apply("fzb"); // String {'fzb'}
// 2、bind的显示绑定高于隐式绑定(两个列子,第二个比较更明显)
var bar = obj.foo.bind("fzb");
bar(); // String {'fzb'}
function foo() {
console.log(this);
}
var info = {
name: "info",
foo: foo.bind("fzb"),
};
info.foo(); // String {'fzb'}
3、new绑定的优先级高于隐式绑定
var obj = {
name: "obj",
foo: function () {
console.log(this);
},
};
var s = new obj.foo(); // foo {}
4、new绑定优先级高于显示绑定
// call/apply一使用就会是函数指向,不能和new绑定比较
function foo() {
console.log(this);
}
var fn = foo.bind("fzb");
var s = new fn(); //foo {}
特殊绑定
忽略显示绑定
理论上来说,显示绑定传入指定的对象,那么函数内的this指向应该指向这个对象,如果传入的是undefined和null呢?
apply、bind的结果也一样的
function foo() {
console.log(this);
}
var obj = {
name: "obj",
foo: foo,
};
foo.call(null); // window
foo.call(undefined); // window
obj.foo.call(null); // window
obj.foo.call(undefined); // window
对于数组方法呢?
[1, 2, 3, 4].forEach(function (item) {
console.log(this); // window
}, null);
间接函数引用
var obj1 = {
name: "obj1",
foo: function () {
console.log(this);
},
};
var obj2 = {
name: "obj2",
};
obj2.foo = obj1.foo;
obj2.foo(); // {name: 'obj2', foo: ƒ}
// 这时一个赋值语句,会将foo函数单独拿出来执行,是一个独立函数调用。
(obj2.foo = obj1.foo)(); // window
this规则之外-箭头函数
this的四条规则对箭头函数是没有用的,箭头函数本身不绑定this,是由外层作用域来决定的。
var name = "window";
var obj = {
name: "obj",
foo: () => {
console.log(this.name);
},
bar: function () {
return () => {
console.log(this.name);
};
},
};
obj.foo(); // window
obj.bar()(); // obj
面试题练习
面试题一:
面试题二:
面试题三:
面试题四:
以上是关于一文搞定JavaScript的this指向问题的主要内容,如果未能解决你的问题,请参考以下文章