1. “::” 操作符
this
绑定语法,提供了一种新的操作符::
,用于进行便捷的this
绑定。
主要有以下两种用法:
(1)串联
import { map, takeWhile, forEach } from "iterlib";
getPlayers()
::map(x => x.character())
::takeWhile(x => x.strength > 100)
::forEach(x => console.log(x));
(2)单独使用
Promise.resolve(123).then(::console.log);
单独使用时,::
后面必须是x.y
,x[y]
或super.x
,super[x]
的形式,
否则会报Syntax Error,以下语法规则说明了这一点。
BindExpression :
<i> </i>:: MemberExpression
- It is a Syntax Error if the derived MemberExpression is not
MemberExpression : MemberExpression . Identifier,
MemberExpression : MemberExpression [ Expression ],
or SuperProperty - It is a Syntax Error if the derived NewExpression is PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList and CoverParenthesizedExpressionAndArrowParameterList ultimately derives a phrase that, if used in place of NewExpression, would produce a Syntax Error according to these rules. This rule is recursively applied.
<u></u>
SuperProperty :
super [ Expression ]
super . IdentifierName
2. The Reference Specification Type
The Reference Specification Type,是一个语言规范内置的类型(ECMAScript Specification Types)。
Reference Specification Type包含两种值,Reference
和Super Reference
。
(1)Reference是一种数据结构,包括base value
,referenced name
,
以及strict reference flag
三个组成部分。
(2)Super Reference,多了一个thisValue
字段,
用于处理super()
以及super.method()
调用过程。
The base value component is either undefined, an Object, a Boolean, a String, a Symbol, a Number, or an Environment Record.
The referenced name component is a String or Symbol value.
与之相关联有几个函数,下文会用到:
(1)GetBase(V)会返回一个Reference的base value
。
(2)GetValue用于获取词法环境中绑定的值,或者对象的属性值。
(3)GetThisValue,对于Reference则返回base value
,
否则对于Super Reference则返回它的thisValue
字段。
2. 绑定规则
(1)串联
BindExpression :
<i> </i>LeftHandSideExpression :: [lookahead ≠ new] MemberExpression
- Let baseReference be the result of evaluating LeftHandSideExpression.
- Let baseValue be GetValue(baseReference).
- Let targetReference be the result of evaluating MemberExpression.
- Let target be GetValue(targetReference).
- If IsCallable(target) is false, throw a TypeError exception.
- Let F be ? BoundFunctionCreate(target, baseValue, «»).
- Return InitializeBoundFunctionProperties(F, target).
<u></u>
根据BoundFunctionCreate (targetFunction, boundThis, boundArgs)的定义,我们知道,
BoundFunctionCreate
的第二个参数就是所创建函数的this
值,
因此GetValue(baseReference)
的值就是this
。
根据GetValue
的定义可知,
如果baseReference
是一个词法变量,则返回它的绑定值,
如果它是一个对象属性,就返回这个属性值。
结论:
如果::
是串联使用,那么this
会被绑定为::
左边的值,
无论左边是一个变量(例如,x::y
,y
中的this
绑定为x
的值),
还是对象的属性(例如,a.b::y
,y
中的this
绑定为a.b
的值)。
(2)单独使用
BindExpression :
<i> </i>:: MemberExpression
- Let targetReference be the result of evaluating MemberExpression.
- Assert: IsPropertyReference(targetReference) is true.
- Let thisValue be GetThisValue(targetReference).
- Let target be GetValue(targetReference).
- If IsCallable(target) is false, throw a TypeError exception.
- Let F be ? BoundFunctionCreate(target, thisValue, «»).
- Return ? InitializeBoundFunctionProperties(F, target).
<u></u>
同理,GetThisValue(targetReference)
的值就是所创建函数的this
值,
根据语法规则,MemberExpression
必须是x.y
,x[y]
或super.x
,super[x]
的形式,
x.y
和x[y]
是Reference,base value都是x
的值,
super.x
和super[x]
是Super Reference,thisValue字段是父类对象。
结论:
::x.y
,::x[y]
的this
指向x
的值,
而::super.x
与::super[x]
中的this
指向父类对象。
参考
tc39/ecma262
proposals/stage-0-proposals.md
ECMAScript This-Binding Syntax
ECMAScript 2017 Language Specification