The this parameter in arrow function - Arrow function中的this参数

当我在阅读Secrets of the JavaScript Ninja一书时,在该书的第四章末尾的Exercises中有这样两个问题。

When running the following code, which of the assertions will pass?
function Ninja(){
  this.whoAmI = () => this;
}
var ninja1 = new Ninja();
var ninja2 = {
  whoAmI: ninja1.whoAmI
};
assert(ninja1.whoAmI() === ninja1, "ninja1 here?");
assert(ninja2.whoAmI() === ninja2, "ninja2 here?");
Which of the following assertions will pass?
function Ninja(){
  this.whoAmI = function(){
    return this;
  }.bind(this);
}
var ninja1 = new Ninja();
var ninja2 = {
  whoAmI: ninja1.whoAmI
};
assert(ninja1.whoAmI() === ninja1, "ninja1 here?");
assert(ninja2.whoAmI() === ninja2, "ninja2 here?");

起初,我的猜想是:

  • 第一个问题的答案是:ninja1.whoAmI() === ninja1,ninja1.whoAmI() === window
  • 第二个问题的答案是:ninja1.whoAmI() === ninja1,ninja2.whoAmI() === ninja1

对于第一个问题的回答,我不确定。因为书中对于arrow functionthis的解释,我也不是很理解。原文是这样的:arrow functions don’t get their own implicit this parameter when we call them; instead they remember the value of the this parameter at the time they were created. 当我们调用arrow functions时,它们没有自己的隐式的this参数;它们只记得 在创建它们时 this参数的值

对于第二个问题的回答,我的根据是书中的这样一段话:

The bind method is available to all functions, and is designed to 
create and return a new function that’s bound to the passed-in 
object (in this case, the button object). The value of the this 
parameter is always set to that object, regardless of the way the 
bound function was invoked. Apart from that, the bound function 
behaves like the originating function, because it has the same code 
in its body.

所有的`function`都有`bind method`这个方法,该方法创建并返回
一个`新的function`,这个`新的function`被绑定到传入的对象上。
不管`新的function`是以何种方式被调用的,在该`新的function`中 
`this`的值永远都是传入的对象。
除此以外,`新的function`在行为上 和原来的函数类似,
因为`新的function`和原来的函数`function body`有着同样的代码。

所以我对上面的代码加了一些assert,并运行它。因为把问题1和问题2的测试都放在一起了,所以对问题2的代码做了些改动 以便测试。

<!DOCTYPE html>
<html>
<head>
  <title>Using arrow functions to work around callback function contexts</title>
  <meta charset="utf-8">
  <script src="../assert.js"></script>
  <link rel="stylesheet" type="text/css" href="../assert.css">
</head>
<body>
  <script>
    function Ninja(){
      this.whoAmI = () => this;
    }

    var ninja1 = new Ninja();
    var ninja2 = {
      whoAmI: ninja1.whoAmI
    };
    
    assert(ninja1.whoAmI() === ninja1, "ninja1.whoAmI() === ninja1");
    assert(ninja2.whoAmI() === ninja2, "ninja2.whoAmI() === ninja2");

    assert(ninja2.whoAmI() === window, "ninja2.whoAmI() === window");
    assert(ninja2.whoAmI() === ninja1, "ninja2.whoAmI() === ninja1");

    assert(ninja1.whoAmI === ninja2.whoAmI, "ninja1.whoAmI === ninja2.whoAmI");


    function Person(){
      this.whoAmI = function(){
        return this;
      }.bind(this);
    }

    var p1 = new Person();
    var p2 = {
      whoAmI: p1.whoAmI
    }

    assert(p1.whoAmI() === p1, "p1.whoAmI() === p1");
    assert(p2.whoAmI() === p2, "p2.whoAmI() === p2");

    assert(p2.whoAmI() === window, "p2.whoAmI() === window");
    assert(p2.whoAmI() === p1, "p2.whoAmI() === p1");

    assert(p1.whoAmI === p2.whoAmI, "p1.whoAmI === p2.whoAmI");

  </script>
  
</body>
</html>

运行结果如下图:

Screen Shot 2018-04-19 at 6.04.33 PM.png
  • 根据运行结果的第五行和第十行,可以看出ninja1.whoAmIninja2.whoAmI是同一个函数。
  • ninja2.whoAmI() === ninja1这个结果在问题2中不显得那么奇怪,因为书中的话 已经解释的相当清楚了。
  • 但是ninja2.whoAmI() === ninja1这个结果在问题1中是显得有点奇怪的,因为 它和我预期的ninja2.whoAmI() === window 不一样。

所以我就搜了下,Stack Overflow中有类似的 但不完全一样的问题,但是其中的一些回答也适用于我的问题。
Arrow functions bind their this when they are created do not have this, arguments or other special names bound at all - when the object is being created the name thisis found in the enclosing scope.
Arrow functions没有this arguments这些参数。当Arrow functions被创建时,this参数是在enclosing scope中被找到的。

并且下面的两段代码近似相等

function Ninja(){
      this.whoAmI = () => this;
}

can be translated into a vague approximation of the arrow syntax in ES5:

function Ninja(){
  this.whoAmI = function(){
    return this;
  }.bind(this);
}

在问题1中的结果ninja2.whoAmI() === ninja1也就得到了解释。


所以说,书中的话并不是那么的准确:arrow functions don’t get their own implicit this parameter when we call them; instead they remember the value of the this parameter at the time they were created. 换个更准确的说法,就应该是:Arrow functions bind their this when they are created do not have this, arguments or other special names bound at all - when the object is being created the name thisis found in the enclosing scope.
尽管解决了一些我的疑问,但是 我还是不清楚: 即,函数是何时被创建的。

通过回顾之前的一篇文章,让我对函数是合适创建的有了一些新的认识:
编译时 对所有代码进行逐行检测 。检测到所有的var(var当然也包括函数的定义,但是不包括赋值表达式右侧的函数定义),并分配存储空间。 注意是先编译后执行,编译时为所有的变量的定义 分配好存储空间(函数的定义也视作var声明,因此函数的定义 也被分配了存储空间),要区分compilation phase和execution phase。并且编译也不是一次性完成的,每当遇到要执行的函数时,会对要执行的函数进行编译(大概 函数就是在此时被创建的吧?)。因此编译和执行时交叉进行的。

转载请注明出处

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容