前言
对于前端小白或者 JavaScript 基础不是很牢固的人来说,this 一直是一个神秘的存在。很多资料里都有 this 的相关说明,也可以参考 详解 JavaScript 中 this 机制。今天把见过的关于 this 的面试题集中探讨一下。
试题 1
var length = 10;
function fn() {
console.log(this.length);
};
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);//输出是什么?
解析:
输出结果为 10 , 2。
首先在调用 fn() 的时候,可以理解为 window.fn()。this 虽然变幻莫测,但是有一点需要牢牢记住,就是谁调的,this 指的就是谁。所以结果为 10。
其次在执行 arguments0 时,通过 arguments 的方式去调用数组里面的函数,其函数内部的 this 指的就是 arguments。还是那句话,谁调用指的就是谁,这里是通过 arguments 数组对象调用的。所以指的就是 arguments。而 length 就是数组的元素个数,有 fn 和 1,所以结果为2。
思考:
如果把第一个 var 改变 let。输出又是什么昵?如下:
let length = 10;
function fn() {
console.log(this.length);
};
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]();
}
};
obj.method(fn, 1);//输出是什么?
解析:
输出结果为 0,2。
输出 0 是因为 var 跟 let 的区别,let 有块级作用域,其声明的变量不会放在全局 window 中。所以在调用 fn() 的时候,window.length 还是原始的 0。
输出 2 跟以上一样。
试题 2
var a=1;
function printA(){
console.log(this.a);
}
var obj={
a:2,
foo:printA,
bar:function(){
printA();
}
}
obj.foo();
obj.bar();
var foo=obj.foo;
foo();
解析:
这个题目跟第1题挺像的。
- obj.foo() 的输出结果为 2。因为 foo 调用的对象是 obj,所以 this 指的就是 obj。故结果为 2。
- obj.bar() 的输出结果为 1。因为 printA() 调用的对象是 window。所以 this 指向的就是 window,顾结果为 1。
- foo() 的输出结果为 1。虽然 foo 是对象 obj 内部的方法。但是 this 是在函数执行的时候确定的,并不是定义的时候。而在执行的时候 foo() 可以看成是 window.foo() 。其调用对象是 window,顾结果为 1。
思考:如果把 var a =1
改成 let a =1
,输出的结果又是什么昵。
解析:window 内部肯定是没有 a 这个属性的。所以原先输出 1 的结果就是 undefined 了
试题 3
var a = 100;
var obj = {
a:10,
timer: function () {
setTimeout(function () {
console.log(this.a);
})
}
};
obj.timer();
解析:
obj.timer() 的输出结果为 100。这里可能有点迷惑了。不是说好谁调用 this 指的就是谁嘛,这里明明是被 obj 调用的。为啥结果不是 10 昵?这是因为有定时器,定时器和匿名函数内的作用域指的是全局环境,也就是 window ,所以结果为 100。
思考:如果想打印的结果为 10 应该怎么改昵?
解析:直接将 setTimeout 的回掉改成 箭头函数 ()=>{}
这种形式即可。ES6 的箭头函数内部的 this 指向的是它上层作用域的 this 。因为 timer 是被 obj 调用的,所以其内部的 this 指向的就是 obj ,即结果为 10。
持续更新中…