为了助记:
以下是 20 道考察 this指向的题目,涵盖各种场景。自己先思考答案,再看解析:
基础题(1-10)
1. 全局调用
var a = 1;
function test() {
console.log(this.a);
}
test();
2. 对象方法调用
var obj = {
a: 2,
test: function() {
console.log(this.a);
}
};
obj.test();
3. 方法赋值后调用
var a = 1;
var obj = {
a: 2,
test: function() {
console.log(this.a);
}
};
var foo = obj.test;
foo();
4. 多层对象
var a = 1;
var obj1 = {
a: 2,
obj2: {
a: 3,
test: function() {
console.log(this.a);
}
}
};
obj1.obj2.test();
5. 回调函数
var a = 1;
var obj = {
a: 2,
test: function() {
console.log(this.a);
}
};
setTimeout(obj.test, 100);
6. 构造函数
function Person(name) {
this.name = name;
console.log(this);
}
var p = new Person('Alice');
7. 箭头函数
var a = 1;
var obj = {
a: 2,
test: () => {
console.log(this.a);
}
};
obj.test();
8. 嵌套箭头函数
var a = 1;
var obj = {
a: 2,
test: function() {
return () => {
console.log(this.a);
};
}
};
obj.test()();
9. 方法中的函数
var a = 1;
var obj = {
a: 2,
test: function() {
function inner() {
console.log(this.a);
}
inner();
}
};
obj.test();
10. 立即执行函数
var a = 1;
var obj = {
a: 2,
test: (function() {
console.log(this.a);
})()
};
进阶题(11-20)
11. call/apply
var a = 1;
var obj1 = { a: 2 };
var obj2 = { a: 3 };
function test() {
console.log(this.a);
}
test.call(obj1);
test.apply(obj2);
12. bind
var a = 1;
var obj = { a: 2 };
function test() {
console.log(this.a);
}
var boundTest = test.bind(obj);
boundTest();
var obj2 = { a: 3, test: boundTest };
obj2.test();
13. bind + new
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
var obj = {};
var BoundPerson = Person.bind(obj);
var p = new BoundPerson('Alice');
p.sayName();
console.log(obj.name);
14. 严格模式
'use strict';
var a = 1;
function test() {
console.log(this);
}
test();
15. 箭头函数 + call
var a = 1;
var obj = { a: 2 };
var test = () => {
console.log(this.a);
};
test.call(obj);
16. 事件处理器
// 假设在浏览器中
var button = document.createElement('button');
button.textContent = 'Click me';
var obj = {
a: 1,
handleClick: function() {
console.log(this.a);
}
};
button.addEventListener('click', obj.handleClick);
button.click(); // 模拟点击
17. 类中的 this
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
sayNameArrow = () => {
console.log(this.name);
}
}
const p = new Person('Bob');
const { sayName, sayNameArrow } = p;
sayName();
sayNameArrow();
18. 原型链上的 this
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
var p1 = new Person('Alice');
var p2 = new Person('Bob');
p1.sayName();
p2.sayName();
19. 多层 bind
var obj1 = { a: 1 };
var obj2 = { a: 2 };
var obj3 = { a: 3 };
function test() {
console.log(this.a);
}
var test1 = test.bind(obj1);
var test2 = test1.bind(obj2);
var test3 = test2.bind(obj3);
test3();
20. 综合题
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1, 2, 3);
挑战题(额外)
21. 链式调用
var obj = {
value: 1,
increment: function() {
this.value++;
return this;
},
getValue: function() {
return this.value;
}
};
console.log(obj.increment().increment().getValue());
22. 模块模式
var calculator = (function() {
var value = 0;
return {
add: function(x) {
value += x;
return this;
},
getValue: function() {
return value;
},
reset: function() {
value = 0;
}
};
})();
calculator.add(5).add(3);
console.log(calculator.getValue());
23. 数组方法中的 this
var obj = {
data: [1, 2, 3, 4, 5],
multiplier: 2,
multiply: function() {
return this.data.map(function(item) {
return item * this.multiplier;
});
}
};
console.log(obj.multiply());
24. 修复数组方法中的 this
var obj = {
data: [1, 2, 3, 4, 5],
multiplier: 2,
multiply: function() {
return this.data.map(function(item) {
return item * this.multiplier;
}, this);
}
};
console.log(obj.multiply());
25. Proxy 中的 this
var target = {
value: 1,
getValue: function() {
return this.value;
}
};
var handler = {
get: function(obj, prop) {
if (prop === 'value') {
return 100;
}
return obj[prop];
}
};
var proxy = new Proxy(target, handler);
console.log(proxy.getValue());
答案解析指南
回答时,考虑以下因素:
- 调用方式(普通函数、方法、构造函数、call/apply/bind)
- 是否严格模式
- 箭头函数 vs 普通函数
- 事件处理器
- 回调函数
- 嵌套函数
- 类方法
- 原型方法
- 立即执行函数
- 链式调用
学习建议
- 先自己写出每道题的答案
- 在浏览器控制台或 Node.js 中运行验证
- 对于错误的题目,仔细分析原因
- 总结
this的绑定规则 - 尝试修改代码,看输出如何变化
具体解析,请移步: JavaScript this 指向 - 练习题 - 详细解析