19.2 Function对象

19.2.1 Function 构造函数

Function的构造函数是%Function%这个内置对象,并且是全局对象global的Function属性。当Function不是以构造函数的形式调用时,会创建并返回一个新的Function对象。因此Function(...)这种调用方式和使用相同参数的对象创建表达式new Function(...)是相等的。

Function构造函数被设计成可继承的,他能在定义class时的extends子句中使用。子类构造函数想要继承Function所规定的行为,必须包含super调用,从而调用Function构造函数,进而创建并且初始化一个具有必要的内置的函数行为的对象。所有定义函数对象的ECMAScript语法形式都创建了一个Function对象。除了内置的Generator Function,没有语法是创建Function子类实例的。

19.2.1.1 Function (p1,p2, … ,pn,body)

最后一个参数定义了函数体(可执行代码),其余之前的参数定义了形参。

当Function函数以p1,p2, … ,pn,body(n可能为0,就是说可能没有参数,并且body也可能没有提供)为参数调用时,会执行以下步骤:

注意:允许不给每一个形参定义一个参数,比如说,下面的三个表达式的结果是一样的

new Function("a", "b", "c", "return a+b+c")

new Function("a, b, c", "return a+b+c")

new Function("a, b", "c", "return a+b+c")

19.2.1.1.1 CreateDynamicFunction(constructor, newTarget, kind, args)

这个抽象CreateDynamicFunction以参数 constructor, newTarget, kind, and args调用. constructor 这个行为要执行的构造函数。 newTarget是new 初始化应用于的, kind 要么是"normal" 或者 "generator", args 是一个包含实际传给constructor 的参数的List 。会执行以下步骤:

  1. if newTarget is undefined, let newTarget be constructor.

  2. If kind is "normal", then

    • Let goal be the grammar symbol FunctionBody.
    • Let parameterGoal be the grammar symbol FormalParameters.
    • Let fallbackProto be "%FunctionPrototype%".
  3. Else,

    • Let goal be the grammar symbol GeneratorBody.

    • Let parameterGoal be the grammar symbol FormalParameters[Yield].

    • Let fallbackProto be "%Generator%".

  4. Let argCount be the number of elements in args.

  5. Let P be the empty String.

  6. If argCount = 0, let bodyText be the empty String.

  7. Else if argCount = 1, let bodyText be args[0].

  8. Else argCount > 1,

    • Let firstArg be args[0].

    • Let P be ? ToString(firstArg).

    • Let k be 1.

    • Repeat, while k < argCount-1

    • Let nextArg be args[k].

      • Let nextArgString be ? ToString(nextArg).

      • Let P be the result of concatenating the previous value of P, the String "," (a comma), and nextArgString.

      • Increase k by 1.

    • Let bodyText be args[k].

  9. Let bodyText be ? ToString(bodyText).

  10. Let parameters be the result of parsing P, interpreted as UTF-16 encoded Unicode text as described in 6.1.4, using parameterGoal as the goal symbol. Throw a SyntaxError exception if the parse fails.

  11. Let body be the result of parsing bodyText, interpreted as UTF-16 encoded Unicode text as described in 6.1.4, using goal as the goal symbol. Throw a SyntaxError exception if the parse fails.

  12. If bodyText is strict mode code, then let strict be true, else let strict be false.

  13. If any static semantics errors are detected for parameters or body, throw a SyntaxError or a ReferenceError exception, depending on the type of the error. If strict is true, the Early Error rules for StrictFormalParameters:FormalParameters are applied. Parsing and early error detection may be interweaved in an implementation dependent manner.

  14. If ContainsUseStrict of body is true and IsSimpleParameterList of parameters is false, throw a SyntaxError exception.

  15. If any element of the BoundNames of parameters also occurs in the LexicallyDeclaredNames of body, throw a SyntaxError exception.

  16. If body Contains SuperCall is true, throw a SyntaxError exception.

  17. If parameters Contains SuperCall is true, throw a SyntaxError exception.

  18. If body Contains SuperProperty is true, throw a SyntaxError exception.

  19. If parameters Contains SuperProperty is true, throw a SyntaxError exception.

  20. If kind is "generator", then

    • If parameters Contains YieldExpression is true, throw a SyntaxError exception.
  21. If strict is true, then

    • If BoundNames of parameters contains any duplicate elements, throw a SyntaxError exception.
  22. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).

  23. Let F be FunctionAllocate(proto, strict, kind).

  24. Let realmF be the value of F's [[Realm]] internal slot.

  25. Let scope be realmF.[[GlobalEnv]].

  26. Perform FunctionInitialize(F, Normal, parameters, body, scope).

  27. If kind is "generator", then

    • Let prototype be ObjectCreate(%GeneratorPrototype%).

    • Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).

  28. Else, perform MakeConstructor(F).

  29. Perform SetFunctionName(F, "anonymous").

  30. Return F.

注意:在调用CreateDynamicFunction创建函数时,prototype属性都会被自动创建,为了函数有可能会被当作构造函数使用这种可能性

19.2.2 Properties of the Function Constructor

函数构造器本身就是一个内置的函数对象,其[[Prototype]]属性是内置属性%FunctionPrototype%. 其[[Extensible]]属性值为true 其还有如下属性:

19.2.2.1 Function.length

这是一个数据属性,其特性有{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }

19.2.2.2 Function.prototype

Function.prototype的值为%FunctionPrototype%,内置的函数原型对象。 其特性有{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

19.2.3 Function.prototype的属性

函数原型对象是内置的%FunctionPrototype%,它也是一个内置的函数对象,当被调用时,它接受任何参数,并且返回undefined。它没有[[Construct]]这个内置方法,所以它不是一个构造函数。

Function.prototype被定义为一个函数对象,是为了确保和ECMAScript2015之前的ECMAScript代码兼容。

其[[Prototype]]内置属性值为%ObjectPrototype%。内置属性[[Extensible]]值为true 其没有prototype属性 其length属性值为0 其name值是空字符串

19.2.3.1 Function.prototype.apply(thisArg, argArray)

当apply函数是被func对象以thisArg和argArray为参数调用时,会执行以下步骤:

  1. If IsCallable(func) is false, throw a TypeError exception.
  2. If argArray is null or undefined, then
    • Perform PrepareForTailCall().
    • Return ? Call(func, thisArg).
  3. Let argList be ? CreateListFromArrayLike(argArray).
  4. Perform PrepareForTailCall().
  5. Return ? Call(func, thisArg, argList).

注意1: thisArg传递给Call时不会被修改为this值,这和ECMAScript3不同,当thisArg为undefined或者null时,为被替换为global object,并且ToObject这个操作会被应用于所有的其他类型值,并且结果会被以this值传递给Call。尽管thisArg直接被传递不会被修改,非严格模式代码依然会在进入函数时执行转换。

注意2: 如果func是一个箭头函数或者绑定函数,那么thisArg会在第五步中的 [[Call]] 所忽略。

19.2.3.2 Function.prototype.bind ( thisArg, ...args)

当bind函数以thisArg和0个或多个参数args调用时,会执行以下步骤:

  1. Let Target be the this value.
  2. If IsCallable(Target) is false, throw a TypeError exception.
  3. Let args be a new (possibly empty) List consisting of all of the argument values provided after thisArg in order.
  4. Let F be ? BoundFunctionCreate(Target, thisArg, args).
  5. Let targetHasLength be ? HasOwnProperty(Target, "length").
  6. If targetHasLength is true, then
    • Let targetLen be ? Get(Target, "length").
    • If Type(targetLen) is not Number, let L be 0.
    • Else,
      • Let targetLen be ToInteger(targetLen).
      • Let L be the larger of 0 and the result of targetLen minus the number of elements of args.
  7. Else let L be 0.
  8. Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor {[[Value]]: L, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
  9. Let targetName be ? Get(Target, "name").
  10. If Type(targetName) is not String, let targetName be the empty string.
  11. Perform SetFunctionName(F, targetName, "bound").
  12. Return F.

注意1: Function.prototype.bind所创建的函数对象是外来对象,他们没有prototype属性

注意2: 如果Target是一个箭头函数或者绑定函数,那么thisArg不会被后续的对F的调用所使用

19.2.3.4 Function.prototype.constructor

其初始值为%Function%

19.2.3.5 Function.prototype.toString ()

当toString在对象func上调用时,会执行以下步骤:

  1. If func is a Bound Function exotic object, then
    • Return an implementation-dependent String source code representation of func. The representation must conform to the rules below. It is implementation dependent whether the representation includes bound function information or information about the target function.
  2. If Type(func) is Object and is either a built-in function object or has an [[ECMAScriptCode]] internal slot, then
    • Return an implementation-dependent String source code representation of func. The representation must conform to the rules below.
  3. Throw a TypeError exception.

toString 表现要求:

  • 表示的字符串必须有FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, 或者 GeneratorMethod的语法,具体是哪个,取决于这个对象的实际特性。
  • 在表示的字符串中使用或者替换空格、行终结符、分号取决于具体的实现。
  • 如果这个对象时使用ECMAScript定义的,并且其返回不是MethodDefinition 或者 GeneratorMethod 形式的,那么这个字符串被eval在创建这个对象的词法上下文中执行时,会返回一个新的功能相同的对象。在这种情况下,源代码中不能随便使用任何没有在源代码中声明的变量,尽管这个变量时声明在同一个作用域内
  • 如果实现不能产生一个满足以上标准的源代码字符串,那么必然返回一个字符串,其使用eval时会抛出SyntaxError异常。

19.2.3.6 Function.prototype [ @@hasInstance ] ( V )

当@@hasInstance被F对象以V为参数调用时,会执行以下步骤:

  1. F为this值
  2. 返回OrdinaryHasInstance(F, V) 这个函数的name值为"[Symbol.hasInstance]" 这个属性的特性为{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }

注意: 这是大多数函数继承的@@hasInstance的默认实现,它时被instanceof这个操作符调用的,用来确定某个值是否是某个构造函数的实例,如以下表达式:v instanceof F,会被执行为F[@@hasInstance](v).一个构造函数可以控制哪个对象是其实例,只要给构造函数提供一个不同的@@hasInstance方法即可

这个属性是不可写,不可配置的,为了防止被篡改。它可能被用来识别绑定函数的目标函数。

19.2.4 函数实例

每一个函数实例都是ECMAScript的函数对象,其有表27中的内置方法,使用Function.prototype.bind创建的函数实例有表28中的内置属性。函数实例有如下属性:

19.2.4.1 length

length的值是一个整数,表明这个函数所期望的参数个数。然而这门语言允许函数以任意个参数的形式被调用,当调用参数个数和length值不一致时,其行为取决于函数本身。 这个属性有如下特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

19.2.4.2 name

name值是一个字符串,其是用来描述这个函数的。name没有语义意义,但是它一般是变量或者属性在定义函数的时候使用。这个属性具有如下特性: [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true } 匿名函数没有一个上下文相关的name值,所以他们本身没有name属性,但是会继承自%FunctionPrototype%.

19.2.4.3 prototype

能被当作构造函数使用的函数实例有prototype属性。任何时候这样的一个函数实例被创建的时候,也会创建一个普通对象,并且其初始值就是prototype属性。除了另外定义的以构造函数的形式被调用,其prototype属性用来初始化[[prototype]]属性。 其特性为{ [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.

注意:以Function.prototype.bind创建的,或者 MethodDefinition 和箭头函数语法定义的函数都没有prototype属性

results matching ""

    No results matching ""