资讯专栏INFORMATION COLUMN

简单易懂的ECMA规范导读1 that's this

yintaolaowanzi / 3227人阅读

摘要:本文不是标准的中文翻译,也不是的入门教程,本文虽然以的常见问题切入,但并不适合想要快速了解这些问题的人才是快速了解问题的正解。尽量以英文原版为基础,为了流畅,可能会使用某些名词的中文翻译,但会将匹配的英文名词以此种样式中出现一次以避免误解。

简单易懂的ECMA规范导读1

最近混SF,恰巧又逢工作方面有了NodeJS的机会,迫切地有教别人怎么写JS的需求,
我发现JS这个东西其实真没那么容易理解。

为了加深和纠正自己对JS的理解,也为了以后能直接甩别人一脸文章,所以开始挖这样一个大坑:简单易懂的ECMA规范导读
希望能以专题的形式有线索地基于ECMA标准介绍Javascript的方方面面。本文不是ECMA标准的中文翻译,也不是Javascript的入门教程,
本文虽然以JS的常见问题切入,但并不适合想要快速了解这些问题的人(Google才是快速了解问题的正解)。
本文的聚焦于标准如何决定了JS的各种行为,JS引擎的水面下在发生些什么。

本文描述的是ECMA262的5.1版本 也是现在最为流行和主流的标准,
现代浏览器和NodeJS默认均遵循此标准。尽量以英文原版为基础,为了流畅,可能会使用某些名词的中文翻译,
但会将匹配的英文名词以此种样式中出现一次以避免误解。

Topic1. that"s this

我们的第一个话题是:this指向哪里?

什么是this

11.1.1 The this Keyword

  

The this keyword evaluates to the value of the ThisBinding of the current execution context.

计算this关键字时,取当前执行上下文的ThisBinding的值

10.3 Execution Contexts

执行上下文Execution Context 从逻辑上形成栈结构,栈顶(活跃)的执行上下文包含了追踪当前正在执行的代码的全部状态。

执行上下文包含了LexicalEnvironment、VariableEnvironment和ThisBinding三部分,在这个话题中我们主要关心ThisBinding,
也就是代码中出现this所代指的值的绑定

全局代码中的this

从最简单的开始

10.4.1 Entering Global Code
在进入全局代码的流程中,规范明确指出:全局代码对应的执行上下文中,

  

Set the ThisBinding to the global object.

所以全局代码中,this指向全局对象

函数调用表达式时提供的this值

注意:this值this value是不同于this关键词的概念,是调用[[Call]]内部方法的参数之一,并不等同于用户代码中的this关键字

函数调用表达式CallExpression的过程中,按照标准的描述,
计算this值的伪代码如下

if Type(ref) is 
    if IsPropertyReference(ref)
        thisValue := getBase(ref)
    else # assert Type(getBase(ref)) is 
        thisValue := getBase(ref).ImplicitThisValue()
else
    thisValue := undefined

ref是函数调用参数左侧(括号左侧)的表达式计算的结果

引用类型常见的有

标示符引用Identifier Reference
即变量引用,引用base是环境记录Environment Record

字面量引用Literal Reference
引用base也是环境记录

属性访问Property Accessors
包括点运算和[]运算,引用base是左值

非引用类型常见的有

全部ECMA内置函数和所有用户定义函数的返回结果(例外是host objects,也就是假设DOM之类的宿主对象如果需要,
可以定义一些函数返回引用)

环境记录是前述的执行上下文中的LexicalEnvironment和VariableEnvironment的构成要素

不考虑with语句的话,环境记录只有Declarative Environment Records一种,它的ImplicitThisValue始终返回undefined

综上所述,排除with语句的情况下,想让thisValue不是undefined,就只有属性访问一种办法而已。

计算得到thisValue后,调用被调函数func的[[call]]内部方法,提供thisValue作为this的值

new表达式时提供的this值

new表达式NewExpression的执行过程
基本上委托给了[[Construct]]内部方法,我们看这个方法的定义,
关注其中第8步

  

Let result be the result of calling the [[Call]] internal property of F, providing
obj as the this value and providing the argument list passed into [[Construct]] as args.

其中F是构造函数,而obj是本次新建的对象,非常清楚。

this值如何转变为ThisBinding

前两节我们描述了两种触发函数体内代码的办法各自如何构造this值,但正如前述,this关键字的值是执行上下文中的ThisBinding决定的,
this值转变为ThisBinding的过程发生在调用[[Call]]内部方法时,我们看标准

  

Let funcCtx be the result of establishing a new execution context for function
code using the value of F"s [[FormalParameters]] internal property, the passed
arguments List args, and the this value as described in 10.4.3.

阿哈,第一步就是建立新的执行上下文,其中thisBinding的构建在10.4.3 Entering Function Code
中描述,

if function-code is 
    ThisBinding = thisArg
else if thisArg is null or thisArg is undefined
    ThisBinding = global object
else if Type(thisArg) is not 
    ThisBinding = ToObject(thisArg)
else
    ThisBinding = thisArg


这就是魔术的秘密

null 和 undefined 的this在此时会绑定为全局对象

其他三种非对象 String / Boolean / Number 在此时被转化为对象(auto boxing)

但是,strict mode下不进行任何转换

That"s this in Javascript.

本节思考题:

找找看关于apply和call的标准,为何this会变?

找找看关于bind的标准,哪里体现了bind后的函数内的this无视环境和调用方式,总是固定值?

with语句并不是一个良好的实践,所以我避开了它,不过这可以作为阅读标准的练习:with语句如何影响this关键词?请试着写一句代码展示此种影响

eval的内部的this如何确定?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78089.html

相关文章

  • Brief introduction of how to 'Call, Apply and

    摘要:关于在绝大多数情况下,函数的调用方式决定了的值。不能在执行期间被赋值,并且在每次函数被调用时的值也可能会不同。它们除了参数略有不同,其功能完全一样。它们的第一个参数都为将要指向的对象。 关于 this 在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。 全局 this window.something = ...

    incredible 评论0 收藏0
  • [译]Understanding javascript's 'undefined

    摘要:一个表示编译器检测到一个无效的引用值。在实际情况中,往往是在获取一个未被赋值的引用时被抛出。任何一个函数上下文都有一个被称为活动对象的变量对象。没有找到的话,就会认为引用名没有基础值并抛出的错误。下没有下的属性仅存在于被启动的情况下。 和其他语言相比,javascript中的对于undefined的理解还是有点让人困惑的。特别是试着理解ReferenceErrors错误(x is no...

    galaxy_robot 评论0 收藏0
  • ECMAScript 2018 标准导读

    摘要:标准对象,语义由本规范定义的对象。三个冒号作为分隔符分割数字字符串文法的产生式。所有因为带来的问题,基本上是占着茅坑不拉屎的行为导致。以数组测试操作为例,标准中的描述如下相对于来说,规范中增加了对的处理。 前言 本文是对《ECMAScript 2018 Language Specification》的解读。本文是对标准的概述性导读,不是对 ES2018特性的详细描述,也不会针对某个技术...

    MiracleWong 评论0 收藏0
  • Node.js中Object与Function在ECMA 规范关系

    摘要:一规范中二规范中三规范中四分析过程分析五证明流程 Why in JavaScript both Object instanceof Function and Function instanceof Object return true? 一、ECMA5.1规范中instanceof /* how instanceof is defined by ECMA 5.1 Specificati...

    LdhAndroid 评论0 收藏0
  • es6

    摘要:只要上述版权通知版权许可和免责声明均包含在所有此类副本和衍生物中。它应用于网景后来所有的浏览器中以及微软之后的版本中。年月,这份标准采用快速程序提交给,并被核准成为国际标准。标准第三版在年月会议上通过并在年月作为标准发布。 ECSA-262标准第六版/2015年6月 ECMAScript 2015语言规范 这是 ECMA-262 第六版,ECMAScript 2015 语言规范 HTM...

    blair 评论0 收藏0

发表评论

0条评论

yintaolaowanzi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<