Function bind syntax S0
中文标题:函数绑定语法
- 阶段: Stage 0
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
本提案引入了一个新的 :: 运算符,用于 this 绑定和方法提取,为常见模式(如使用特定 this 调用函数或提取方法)提供语法糖。该运算符具有二元和一元前缀形式,并且在严格模式下绑定函数立即调用时可以进行优化。提案包括运行时语义、早期错误以及未来扩展(绑定构造函数)。目前它仍处于稻草人阶段,已有 Babel 和 esdown 中的早期原型实现。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMAScript 这个绑定语法
本提案引入了一个新的运算符 ::,用于执行 this 绑定和方法提取。
这是绑定运算符稻草人提案的更详细描述。
示例
使用一个以“虚拟方法”模块实现的迭代器库:
使用一个类似于 jQuery 的虚拟方法库:
使用方法提取将 promise 的最终值打印到控制台:
使用方法提取在 DOM 事件发生时调用对象方法:
动机与概述
随着 ECMAScript 6 中箭头函数的引入,显式地将闭包绑定到词法 this 值的需求已大幅减少,从而显著提高了语言可用性。然而,仍有两个用例中,显式的 this 绑定或注入既常见又笨拙。
使用提供的 this 参数调用已知函数:
从对象中提取方法:
本提案引入了一个新的运算符 ::,可以作为这些用例的语法糖。
在其二元形式中,:: 运算符创建一个绑定函数,使得运算符左侧的值绑定为右侧目标函数的 this 变量。
在其一元前缀形式中,:: 运算符创建一个绑定函数,使得所提供的引用的基值绑定为目标函数的 this 变量。
如果绑定函数立即被调用,并且目标函数是严格模式,那么绑定函数本身是不可观察的,绑定运算符可以被优化为高效且直接的函数调用。
注意:如果目标函数不是严格的,那么它可能会使用 function.callee 或 arguments.callee,这将导致行为的可观察差异。
通过为这些用例提供语法糖,我们将启用一类新的“虚拟方法”库,这将比当今使用的标准适配器模式具有可用性优势。
原型实现
语法
早期错误
-
如果派生的 MemberExpression 不是 MemberExpression : MemberExpression . Identifier、MemberExpression : MemberExpression [ Expression ] 或 SuperProperty,则这是一个语法错误。
-
如果派生的 NewExpression 是 PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList,并且 CoverParenthesizedExpressionAndArrowParameterList 最终派生的短语,如果用在 NewExpression 的位置,根据这些规则会产生语法错误,则这是一个语法错误。此规则递归应用。
注意:最后一条规则意味着,如下表达式:
由于第一条规则的递归应用会产生早期错误。
抽象操作:InitializeBoundFunctionProperties ( F, target )
使用参数 F 和 target 的抽象操作 InitializeBoundFunctionProperties 用于设置绑定函数 F 的 "length" 和 "name" 属性。它执行以下步骤:
- 令 targetHasLength 为 HasOwnProperty(target,
"length")。 - 如果 targetHasLength 为
true,则- 令 targetLen 为 ? Get(target,
"length")。 - 如果 Type(targetLen) 不是
Number,则令 L 为0。 - 否则,令 L 为 ToInteger(targetLen)。
- 令 targetLen 为 ? Get(target,
- 否则令 L 为
0。 - 令 status 为 ? DefinePropertyOrThrow(F,
"length", PropertyDescriptor {[[Value]]: L, [[Writable]]:false, [[Enumerable]]:false, [[Configurable]]:true})。 - 令 targetName 为 ? Get(target,
"name")。 - 如果 Type(targetName) 不是
String,则令 targetName 为空字符串。 - 令 status 为 ? SetFunctionName(F, targetName,
"bound")。 - 返回 F。
运行时语义
- 令 baseReference 为求值 LeftHandSideExpression 的结果。
- 令 baseValue 为 GetValue(baseReference)。
- 令 targetReference 为求值 MemberExpression 的结果。
- 令 target 为 GetValue(targetReference)。
- 如果 IsCallable(target) 为
false,抛出TypeError异常。 - 令 F 为 ? BoundFunctionCreate(target, baseValue, «»)。
- 返回 InitializeBoundFunctionProperties(F, target)。
- 令 targetReference 为求值 MemberExpression 的结果。
- 断言:IsPropertyReference(targetReference) 为
true。 - 令 thisValue 为 GetThisValue(targetReference)。
- 令 target 为 GetValue(targetReference)。
- 如果 IsCallable(target) 为
false,抛出TypeError异常。 - 令 F 为 ? BoundFunctionCreate(target, thisValue, «»)。
- 返回 ? InitializeBoundFunctionProperties(F, target)。
未来扩展:绑定构造函数
此语法可以通过引入 绑定构造函数 进行扩展。当二元 :: 运算符后跟 new 关键字时,左侧的构造函数被包装在一个可调用函数中。
运行时语义
- 令 targetReference 为求值 LeftHandSideExpression 的结果。
- 令 target 为 GetValue(targetReference)。
- 如果 IsConstructor(target) 为
false,抛出TypeError异常。 - 令 F 为一个新的内置函数,如绑定构造函数包装函数中所定义。
- 将 F 的 [[BoundTargetConstructor]] 内部槽设置为 target。
- 返回 ? InitializeBoundFunctionProperties(F, target)。
绑定构造函数包装函数
绑定构造函数包装函数是一个匿名的内置函数,具有 [[BoundTargetConstructor]] 内部槽。
当调用一个绑定构造函数包装函数 F 并传递零个或多个 args 时,它执行以下步骤:
- 断言:F 具有 [[BoundTargetConstructor]] 内部槽。
- 令 target 为 F 的 [[BoundTargetConstructor]] 内部槽的值。
- 断言:IsConstructor(target)。
- 令 args 为传递给此函数的所有参数组成的列表。
- 返回 ? Construct(target, args)。