this指向基本原则
全局作用域
在全局作用域中(非严格模式下),this 指向全局对象——在浏览器中为 window。
在严格模式下,全局作用域中的 this 是 undefined。
console.log(this); // 在浏览器中,输出 `window`
对象方法中的this
当一个函数作为对象的方法调用时,this 指向调用该方法的对象。
const obj = {
name: 'Alice',
getName: function() {
console.log(this.name);
}
};
obj.getName(); // `this` 指向 `obj`,输出 'Alice'
构造函数中的this
函数作为构造函数使用时(通过 new 操作符),this 指向新创建的实例对象
function Person(name) {
this.name = name;
}
const person = new Person('Bob');
console.log(person.name); // `this` 指向新创建的 `person` 对象,输出 'Bob'
普通函数中的this
在非严格模式下,普通函数中的 this 默认指向全局对象
在严格模式下,this 为 undefined
function show() {
console.log(this);
}
show(); // 在非严格模式下,输出 `window`
箭头函数中的this
箭头函数不绑定自己的 this,它会继承定义时外层作用域中的 this
无论箭头函数如何被调用,this 的指向都不会改变
const obj = {
name: 'Charlie',
greet: function() {
const arrowFunc = () => {
console.log(this.name);
};
arrowFunc();
}
};
obj.greet(); // `this` 继承自 `greet` 方法,指向 `obj`,输出 'Charlie'
常见的 this 指向误区与困惑
普通函数中的this指向全局对象
const person = {
name: 'Alice',
getName: function() {
function innerFunction() {
console.log(this.name);
}
innerFunction(); // `this` 指向全局对象,输出 `undefined`
}
};
person.getName();
解决方案:可以使用 bind、call、apply 方法显式绑定 this,或者使用箭头函数。
const person = {
name: 'Alice',
getName: function() {
const innerFunction = () => {
console.log(this.name);
};
innerFunction(); // `this` 指向 `person` 对象,输出 'Alice'
}
};
person.getName();
箭头函数的this与bind
箭头函数的 this 是在定义时绑定的,不能通过 bind、call 或 apply 方法改变其 this 指向
const obj = {
count: 1,
increment: function() {
return () => {
this.count++;
return this.count;
};
}
};
const counter = obj.increment();
console.log(counter()); // 输出 2
const newCounter = counter.bind({ count: 10 });
console.log(newCounter()); // 输出 3,因为 `this` 仍然指向 `obj`
回调函数中的this
const button = {
text: 'Click me',
click: function() {
setTimeout(function() {
console.log(this.text);
}, 1000);
}
};
button.click(); // `this` 指向全局对象,输出 `undefined`
解决方案:可以使用箭头函数来继承外层作用域的 this,确保 this 指向正确
const button = {
text: 'Click me',
click: function() {
setTimeout(() => {
console.log(this.text);
}, 1000);
}
};
button.click(); // `this` 指向 `button` 对象,输出 'Click me'
练一练
试题1:
const obj = {
count: 1,
increment: function() {
return () => {
this.count++;
return this.count;
};
}
};
const counter = obj.increment();
console.log(counter());
const newCounter = counter.bind({ count: 10 });
console.log(newCounter());
试题2:
function greet(greeting, punctuation) {
console.log(greeting + ', ' + this.name + punctuation);
}
const person1 = { name: 'Alice' };
const person2 = { name: 'Bob' };
greet.call(person1, 'Hello', '!');
greet.apply(person2, ['Hi', '?']);
const greetPerson1 = greet.bind(person1, 'Welcome');
greetPerson1('!!!');
试题3:
const calculator = {
value: 0,
add: function(a, b) {
this.value = a + b;
return this.value;
},
calculate: function(fn) {
fn();
console.log(this.value);
}
};
const newCalc = {
value: 100
};
calculator.calculate(function() {
calculator.add(5, 10);
});
newCalc.calculate = calculator.calculate;
newCalc.calculate(function() {
calculator.add(15, 20);
});
可以评论写出你的答案以及理解,查缺补漏,更进一步
总结与实践
理解 this 的指向需要对 JavaScript 的执行上下文和调用方式有深刻的理解。通过上面的分析和示例,希望你能更好地掌握 this 的行为,并在实际开发中有效避免常见的陷阱。
• 始终记住:this 的指向由函数的调用方式决定,而不是函数的定义位置。
• 善用箭头函数:箭头函数可以帮助你避免 this 指向的问题,但也要注意它不能被重新绑定。
• 使用工具函数:bind、call 和 apply 是改变 this 指向的有效工具,使用时要明确 this 指向的目标。
编程的世界总是充满未知,期待与你在技术的海洋中再相遇
I just hope my code makes more sense than my life.