在JavaScript中,每个函数都有自己的上下文环境,而this关键字就是指向这个上下文环境,表示当前函数的执行环境。
全局环境下,this指向全局对象(浏览器中为window对象)。
函数内部,this指向调用该函数的对象,如果没有上下文对象,则为window对象。
构造函数中,this指向新创建的对象。
apply()、call()与bind()方法中,this指向指定的对象。
箭头函数内部的this指向在定义时确定。
示例1:
let obj = {
name: '张三',
sayName: function(){
console.log(this.name);
}
}
obj.sayName(); // 输出:张三
示例1中,对象obj调用了sayName方法,因此sayName内部的this指向的就是obj对象。
示例2:
function foo(){
console.log(this === window);
}
foo(); // 输出:true
示例2中,foo函数在全局环境下执行,因此foo内部的this指向全局对象,即window对象。
示例3:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
}
}
let p1 = new Person('张三', 18);
let p2 = new Person('李四', 19);
p1.sayName(); // 输出:张三
p2.sayName(); // 输出:李四
示例3中,Person函数是一个构造函数,我们用new操作符创建了两个新对象p1和p2,这些新对象中的this指向了它们自己。
示例4:
let obj1 = { name: '张三' };
let obj2 = { name: '李四' };
function sayName() {
console.log(this.name);
}
sayName.call(obj1); // 输出:张三
sayName.call(obj2); // 输出:李四
示例4中,我们分别用call()方法将sayName函数的this指向obj1和obj2对象,输出了这两个对象的name属性。
示例5:
let obj1 = { name: '张三' };
let obj2 = { name: '李四' };
let sayName = () => {
console.log(this.name);
}
obj1.sayName = sayName;
obj2.sayName = sayName;
obj1.sayName(); // 输出:undefined
obj2.sayName(); // 输出:undefined
示例5中,我们将箭头函数sayName分别赋值给对象obj1和obj2的sayName属性,并调用了这些属性,但是输出结果都为undefined,这是因为箭头函数内部的this指向在定义时就已经确定,即它没有自己的this值,而是继承了上层的作用域中的this值,也就是全局变量window,因此输出结果为undefined。
JavaScript中的this指向问题比较复杂,需要我们在具体的应用场景中灵活运用。最常用的情况就是函数内部的this,需要注意调用的上下文环境。在需要改变this指向的情况下,可以考虑使用apply()、call()与bind()方法。而对于箭头函数,this的指向在定义时就已经确定好了,需要特别注意。