面试题 - JavaScript 中 this 指向
前言
对于前端小白或者 JavaScript 基础不是很牢固的人来说,this 一直是一个神秘的存在。很多资料里都有 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。 其次在执行 arguments 时,通过 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。
持续更新中…