本文深入解析JavaScript中this关键字的指向规则。通过默认调用、对象方法调用、构造函数及定时器等多种场景示例,阐明this在函数定义时不确定、执行时确定的核心原则,并介绍bind、call、apply改变this指向的方法,帮助开发者彻底掌握this的使用逻辑。
题记
在JavaScript开发中,this的指向规则往往是初学者面临的难点。本文将详细梳理this的指向原则,通过具体案例解析其工作机制,帮助读者彻底厘清这一概念,避免在实际编码中因this指向错误而产生困扰。
开篇
首先明确,this是JavaScript语言中的一个关键字。
它代表函数运行时自动生成的一个内部对象,且仅在函数内部可用。随着函数使用场景的不同,this的值也会随之变化。核心原则在于:this的指向在函数定义阶段无法确定,只有在函数执行时才能明确其指向。实际上,this最终指向的是调用该函数的对象。接下来,我们将通过逐步探索来深入理解这一机制。
探索一
function a() {
var user = "清蒸胖头鱼";
console.log(this.name); //undefined
console.log(this); //Window
}
a();
window.a();//两种结果相同
根据前述原则,this最终指向调用其所在函数的对象。在示例中,函数a是由全局对象window通过点操作符调用的,因此这里的this指向window对象。
探索二
var obj = {
name: '清蒸胖头鱼',
f1: function () {
console.log(this.name);//清蒸胖头鱼
}
};
obj.f1();
再次强调,this的指向在函数定义时是不确定的,仅在函数执行时确定。在示例中,函数f1由对象obj调用,因此此时的this指向obj对象。
探索三
为了彻底理解this的机制,我们需要分析后续的几个典型示例。
var obj = {
a: 5,
b: {
a: 10,
fn: function () {
console.log(this.a); //10
}
}
};
obj.b.fn();
既然原则指出this指向调用其所在函数的对象,为何在示例中并未指向obj对象?
此处需要补充三个关键判断逻辑:
- 若函数内部包含this,但该函数未被上一级对象调用,则this指向window。
- 若函数内部包含this,且该函数被上一级对象调用,则this指向该上一级对象。
- 若函数内部包含this,且该函数涉及多个对象层级,即使由最外层对象调用,this仍指向直接调用它的上一级对象。
至此,相信读者已基本掌握this指向的核心原则:this在函数定义时不确定,仅在执行时确定,最终指向调用该函数的对象。
下面介绍this在不同使用场景下的具体表现。
构造函数(使用new关键字)的情况
function Student() {
this.name = '清蒸胖头鱼';
}
var s1 = new Student();
console.log(s1.name);// 清蒸胖头鱼
对象s1能够访问函数Student内部的name属性,是因为new关键字改变了this的指向,使其指向新创建的对象s1。
// new 关键字执行的过程
1. 在函数体内创建一个空的对象.
2. 让当前this指向这个空的对象.
3. 通过this给当前空的对象添加键值对.
4. 返回已经添加好所有键值对的对象给外面的变量.
定时器中的this指向情况
var num = 0;
function Obj() {
this.num = 1;
this.getNum1 = function () {
console.log(this.num);
};
this.getNum2 = function () {
setInterval(function () {
console.log(this.num);
}, 1000);
};
}
var o = new Obj();
o.getNum1();//1 (o.num)
o.getNum2();//0 (window.num)
o.getNum2()的值之所以为0,即这里的this指向window。再次应用this指向原则:this的指向在函数定义时不确定,只有函数执行时才能确定this指向谁,实际上this最终指向调用其所在函数的对象。
解: this.num所在的函数为定时器setInterval内的function () { console.log(this.num);},根据this指向原则当该函数被执行,this指向它的上一级对象。setInterval,又因setInterval是window点出了的,所以this指向window。
call、apply、bind 改变指向情况
var num = 0;
function Obj() {
this.num = 1;
this.getNum1 = function () {
console.log(this.num);
};
this.getNum2 = function () {
setInterval(function () {
console.log(this.num);
}.bind(this), 1000);//利用bind将this绑定到这个函数上
};
}
var o = new Obj();
o.getNum1();//1 (o.num)
o.getNum2();//1 (o.num)
解释:
bind()方法是Function.prototype上的一个方法。当被绑定函数调用时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this。
根据原则:
未使用bind方法前:被调用时,this.num指向调用其所在函数的对象,即window.setTimeout对象。使用bind方法后:被调用时,将原来的this重新指向→调用getSum2函数(即新this所在的函数)的对象。此处通过构造函数new调用,因此指向o对象。
bind方法在此类场景中较为常用。当然,使用call或apply方法替代也能得到正确结果,但call和apply方法会在调用后立即执行,从而失去延时的效果,使得定时器失去意义。
以上即为详解JavaScript中this指向问题的详细内容,更多关于JavaScript this指向的资料请关注本站其它相关文章!