一道笔试题引起的思考

前两天作了一份笔试题:按照执行顺序列出下面代码的打印内容浏览器

var name = "The Window";
var object = {
    name : "The Object",
    getNameFunc : function(){
        (() => {
            console.log(this.name)
        })()
        return function(){
            console.log(this.name)
        };
    }
};
var func = object.getNameFunc();
func();
func.call(object);
func.apply(object);

可能有些小朋友会被里面那个当即执行函数吓傻。不要紧,先看答案,整段代码输入浏览器,输出以下:闭包

  • The Objectapp

  • The Window函数

  • The Objectthis

  • The Objectspa

OK, 一个一个来分析。code

执行顺序从上往下,这句var func = object.getNameFunc();会产生第一个输出:The Object
想搞明白为何输出这个,必须先知道,this指向谁?
首先,想知道this指向谁,不能看它在哪里被定义,而要看它在哪里被调用,运行object.getNameFunc()时,显而易见地,调用这个函数的是object,当即执行函数里面的this指向objectthis.name天然就是object.nameblog

所以输出The Objectip

那么,接下来,func被赋了什么值?整个getNameFunc()函数吗?get

并非的,object.getNameFunc()函数运行的时候,闭包那段代码没有被执行,只是做为返回结果赋给了func,所以事实上var func = object.getNameFunc()这句等价于:

var func = function() {
     console.log(this.name)
}

如今funcobject就已经没什么关系了,func里面的this天然指向window
所以第二句执行语句func()类似于(注意用词,我这里用的是类似,不是相等):

object.getNameFunc()() //是的,我没打错,两个括号

嘻嘻,是否是有点蒙圈?

上面说了,因为object.getNameFunc()执行后,会对外暴露出一个匿名函数,即return返回的那个匿名函数

function () {
    console.log(this.name)
}

因此object.getNameFunc()()会调起当即执行函数

(function () {
    console.log(this.name)
})()

注意 —— object.getNameFunc()()这个写法只是为了能调用闭包函数,若是在真的在浏览器跑object.getNameFunc()(),事实上会顺序执行输出两个结果:一个是当即执行函数的结果,一个是闭包函数的结果。

clipboard.png

因为object.getNameFunc()赋值给了func,于是使用func()就能够只调用闭包,而不触碰那个当即执行函数。这几句话要当心理解!

一般一个变量未被声明就使用,会指向window.undefined,然而this是不会指向undefined的,像咱们平时定义一个普通函数

function app() {}
// 调用
app()
// 其实是这样调用的
window.app()

因此this会指向windowfunc()天然也等于window.func(),调用方是windowthis.name便是window.name

理解了上面那些,接下来的两句反却是简单了。

func.call(object);
func.apply(object);

callapplythis指向改变至objectthis.name也就是object.name了。

原本写这篇博客以前仍是有点绕的,写完以后脑子就清晰了,相信之后这类题能轻松答上。

相关文章
相关标签/搜索