一道关于this的面试题
最近一段时间学习了一下JS原型相关的知识,其中一个重要的点是关于this关键字的值究竟是什么?讲真,在此之前,虽然我也有用过this这个关键字,但是关于它的值到底是什么一直都没有很明确的一个知识点,有点像靠猜来达成目的的。所以今天写一篇博客来做几个关于this的面试题巩固一下知识,如果中间有错误,希望大家能在评论区指出。
题目一:名字是什么?
var a = {
name:"zhang",
sayName:function(){
console.log("this.name="+this.name);
}
};
var name = "ling";
function sayName(){
var sss = a.sayName;
sss(); //this.name = ?
a.sayName(); //this.name = ?
(a.sayName)(); //this.name = ?
(b = a.sayName)();//this.name = ?
}
sayName();
输出结果如下:
分析:
1.在全局变量中执行函数sayName,先是var sss = a.sayName
,相当于sss = function(){console.log(this.name)}
,然后执行sss(),这时候调用sss()函数就已经不是a.sayName了,而是window环境下的sayName函数,拿到的this的值自然就是"ling";
2.然后执行a.sayName()
,这个a.sayName
函数中的this指向的是对象a,所以拿到的也是对象a中的属性name的值;
3.执行(a.sayName)()
,这一条代码中,可以等价于a.sayName(),括号的作用只是包裹了a.sayName,然后执行它,a.sayName中的this依旧指向的是对象a,所以拿到的还是对象a中的name的值;
4.执行(b = a.sayName)()
,这一条代码中,首先执行了b = a.sayName
这个赋值操作,然后执行b()
,和第一条的执行sss()
没有什么区别,所以拿到的this也是全局变量name;
题目二:名字是什么?(变形一)
var name = "ling";
function sayName(){
var a = {
name:"zhang",
sayName:getName
};
function getName(){
console.log(this.name);
}
getName(); //this.name = ?
a.sayName(); //this.name = ?
getName.call(a);//this.name = ?
}
sayName();
首先来看执行结果:
分析:
1.当执全局上下文中的函数sayName
时,其实就是执行了该函数内的getName(); a.sayName();getName.call(a);
这三个函数,其中第一个getName();
因为是直接在全局上下文中进行的调用,所以该函数内的this指向window,this.name指向window.name的值;
2.执行a.sayName();
时就不一样了,因为a.sayName
是在对象a的上下文中,这时候对象a中的属性sayName
中的值getName
函数的执行上下文就切换到了对象a上,所以这时候的this.name指向a.name;
3.执行getName.call(a)
,这条代码中,加入了call关键字,而call的作用是切换函数的执行上下文(也就是动态改变this的值),而第一个参数是a,相当于把getName
函数绑定到a对象中去,这时候的this指向的就是对象a;
题目三:名字是什么?(变形二)
var name = "ling";
var obj = {
name:"zhang",
sayName:function(){
console.log("this.name="+this.name);
},
callback:function(){
var that = this;
return function(){
var sayName = that.sayName;
that.sayName(); //this.name = ?
sayName();//this.name = ?
}
}
}
obj.callback()()
执行结果:
分析:
1.当执行obj.callback()()
时,中介是分了两个阶段的,第一阶段执行了obj.callback()
,在这一步执行了var that = this;
,这时候的callback函数还是处于对象obj的上下文中,所以这时候的this指向obj,所以that === obj
,然后返回一个函数出来;
2.现在来到第二阶段,执行obj.callback()
返回出来的函数,在这个函数中,首先执行出结果的是that.sayName();
,而在第一阶段中,that指向的是obj,相当于执行obj.sayName()
,得出的结果自然是"zhang";
3.然后有var sayName = that.sayName;
这句话,相当于sayName = function(){console.log(this.name)}
,然后执行这个sayName()
,这时候就要回头看obj.callback()
返回出来的这个函数是在哪里进行调用的了,答案是在window中进行调用的,所以在这个函数中的this指向的是window,所以这时候执行sayName()
,
得到的答案是全局变量name的值"ling"
以上是基于我个人的理解,大家如果看出了什么错误,欢迎在评论区提出。