饥人谷技术博客

一道关于this的面试题

2017-02-27  本文已影响0人  大春春

最近一段时间学习了一下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"

以上是基于我个人的理解,大家如果看出了什么错误,欢迎在评论区提出。

上一篇下一篇

猜你喜欢

热点阅读