[ES] 函数的name属性

一、背景

ECMAScript使用SetFunctionName,给函数添加name属性。

SetFunctionName(F,name[,prefix])

  1. Assert: F is an extensible object that does not have a name own property.
  2. Assert: Type(name) is either Symbol or String.
  3. Assert: If prefix was passed, then Type(prefix) is String.
  4. If Type(name) is Symbol, then
    a. Let description be name's [[Description]] value.
    b. If description is undefined, set name to the empty String.
    c. Else, set name to the concatenation of "[", description, and "]".
  5. If prefix was passed, then
    a. Set name to the concatenation of prefix, code unit 0x0020 (SPACE), and name.
  6. Return ! DefinePropertyOrThrow(F, "name", PropertyDescriptor{[[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).

注:
(1)传入SetFunctionNamename可以是字符串或者Symbol,

const k = Symbol.for('x');
const obj = {
    [k](){ }
};

obj[k].name    // "[x]"

(2)name属性默认是只读的,但它是Configurable的,
因此,可以通过defineProperty修改为可写属性。

const f = function(){ };
f.name = 1;
f.name    // f

Object.defineProperty(f, 'name', {
    writable: true
});

f.name = 1;
f.name    // 1


二、所有细节

*1. 属性定义

PropertyDefinition := PropertyName : AssignmentExpression
如果属性值是一个匿名函数,则将当前正在定义的属性名,设置为匿名函数的name属性。

*2. 赋值

AssignmentExpression := LeftHandSideExpression = AssignmentExpression
如果赋值语句右侧为匿名函数,则将左侧变量的名字,设置为匿名函数的name属性。

3. 解构

*(1)对象解构
AssignmentProperty := IdentifierReference Initializer
在进行对象解构操作时,如果解构变量的默认值为一个匿名函数,则将解构出来的变量名,设置为匿名函数的name属性。

*(2)数组解构
a) AssignmentElement := DestructuringAssignmentTarget Initializer
b) AssignmentElement := DestructuringAssignmentTarget Initializer
在进行数组解构操作时,如果解构变量的默认值为一个匿名函数,则将解构出来的变量名,设置为匿名函数的name属性。

*4. 变量定义

(1)LexicalBinding := BindingIdentifier Initializer
(2)VariableDeclaration := BindingIdentifier Initializer
(3)SingleNameBinding := BindingIdentifier Initializer
变量定义的时候,如果变量值是一个匿名函数,则将变量名设置为匿名函数的name属性。

5. 函数

(1)具名函数声明
FunctionDeclaration := function BindingIdentifier ( FormalParameters ) { FunctionBody }
如果声明的函数有名字,那么就将该名字设置为函数的name属性。

*(2)匿名函数声明
FunctionDeclaration := function ( FormalParameters ) { FunctionBody }
匿名函数声明只能出现在export default后面,此时将"default"设置为匿名函数的name属性。

(3)具名函数表达式
FunctionExpression := function BindingIdentifier ( FormalParameters ) { FunctionBody }
函数表达式定义的函数名,就是函数的name属性。

6. 方法

(1)方法定义
MethodDefinition := PropertyName ( UniqueFormalParameters ) { FunctionBody }
对象的方法名,就是该方法的name属性。

*(2)get方法定义
MethodDefinition := get PropertyName ( ) { FunctionBody }
对象get方法的name属性,为"get"+" "+方法名。(传入SetFunctionNameprefix参数为"get")

*(3)set方法定义
MethodDefinition := set PropertyName ( PropertySetParameterList ) { FunctionBody }
对象set方法的name属性,为"set"+" "+方法名。(传入SetFunctionNameprefix参数为"set")

const obj = {
    get x(){ },
    set y(i){ }
};

Object.getOwnPropertyDescriptor(obj,'x').set.name    // "set x"
Object.getOwnPropertyDescriptor(obj,'x').get.name    // "get y"
7. generator

(1)generator声明
GeneratorDeclaration := function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
如果声明的generator函数有名字,那么就将该名字设置为generator函数的name属性。

*(2)匿名generator声明
GeneratorDeclaration := function * ( FormalParameters ) { GeneratorBody }
匿名generator函数声明只能出现在export default后面,此时将"default"设置为匿名generator函数的name属性。

(3)generator方法
GeneratorMethod := * PropertyName ( UniqueFormalParameters ) { GeneratorBody }
对象generator方法名,就是generator函数的name属性。

(4)具名generator表达式
GeneratorExpression := function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
generator表达式定义的generator函数名,就是generator函数的name属性。

8. class

*(1)class声明
ClassDeclaration := class BindingIdentifier ClassTail
class声明时的名字,就是class的name属性。

*(2)具名class表达式
ClassExpression := class BindingIdentifier ClassTail
具名class表达式定义的名字,就是class的name属性。

注:
class的静态name方法,不会被class的名字覆盖。

class a {
    static name(){ }
}

a.name    // ƒ name(){ }
9. async函数

(1)async函数声明
AsyncFunctionDeclaration := async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
如果声明的async函数有名字,那么就将该名字设置为async函数的name属性。

*(2)async匿名函数声明
AsyncFunctionDeclaration:async function ( FormalParameters ) { AsyncFunctionBody }
匿名async函数声明只能出现在export default后面,此时将"default"设置为匿名async函数的name属性。

(3)async方法
AsyncMethod := async PropertyName ( UniqueFormalParameters ) { AsyncFunctionBody }
对象async方法名,就是async函数的name属性。

(4)async表达式
AsyncFunctionExpression := async functionBindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
async表达式定义的async函数名,就是async函数的name属性。

10. 模块

*(1)模块导出class声明
ExportDeclaration := export default ClassDeclaration
如果模块使用默认方式export default导出class声明,则将"default"设置为class的name属性。

*(2)模块导出表达式
ExportDeclaration := export default AssignmentExpression ;
如果模块使用默认方式export default导出匿名函数表达式,则将"default"设置为函数的name属性。

*11. 动态创建的函数

CreateDynamicFunction( constructor, newTarget, kind, args )
使用Function动态创建的函数,将"anonymous"设置为函数的name属性。

*12. bind返回的函数

Function.prototype.bind ( thisArg, ...args )
bind返回函数的name属性,为"bind"+" "+原函数名。(传入SetFunctionNameprefix参数为"bind")

const f = function(){ };
const g = f.bind(null);

g.name    // "bind f"

参考

ECMAScript 2017 Language Specification
9.2.11 SetFunctionName

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

推荐阅读更多精彩内容