Function.prototype是一个函数

Tra*_*ace 23 javascript prototype

我正在深入研究Javascript原型链.
为了记录我的发现,我画了以下方案:

在此输入图像描述

虽然大多数概念都很清楚,但我只剩下两个相关的问题.我猜测将这些问题集中在这个问题上可能会更好,而不是将它们分开.

  1. 有没有理由Function.prototype成为类型函数而不是对象?
    typeof Function.prototype; //"function"
  2. Function.prototype在JS中是一个'独特的函数',因为它没有像其他函数那样拥有自己的原型属性吗?(是否有一个普遍接受的"名称"来指代它?)

Ori*_*iol 22

原因是ES5规范如此说:

Function原型对象本身就是一个Function对象(它的[[Class]]是"Function"),当被调用时,它接受任何参数并返回undefined.

请注意,在ES5中,将某个类的原型作为该类的成员是很常见的:

我认为它是标准化的,因为类的原型具有该类的内在属性,作为该类的实例.如果它看起来像鸭子,它应该像鸭子一样.因此,在原型本身上而不是在实例上调用原型的方法也应该起作用.

但是,ES6并不喜欢这样.所以它改变了那些行为:

  • Boolean.prototype 是一个没有[[BooleanData]]内部插槽的普通对象.
  • Error.prototype 是一个没有[[ErrorData]]内部插槽的普通对象.
  • Number.prototype 是一个没有[[NumberData]]内部插槽的普通对象.
  • Date.prototype 是一个没有[[DateValue]]内部插槽的普通对象.
  • String.prototype 是一个没有[[StringData]]内部插槽的普通对象.
  • RegExp.prototype 是一个普通的对象,没有[[RegExpMatcher]],也没有RegExp实例对象的任何其他内部插槽.

还有新的"类" (ES6对象不再有[[Class]]):

  • Symbol.prototype 是一个没有[[SymbolData]]内部插槽的普通对象.
  • TypedArray.prototype是一个普通的对象,没有[[ViewedArrayBuffer]],也没有任何其他特定于TypedArray实例对象的内部插槽.
  • Map.prototype 是一个没有[[MapData]]内部插槽的普通对象.
  • Set.prototype 是一个没有[[SetData]]内部插槽的普通对象.
  • WeakMap.prototype 是一个没有[[WeakMapData]]内部插槽的普通对象.
  • WeakSet.prototype 是一个没有[[WeakSetData]]内部插槽的普通对象.
  • ArrayBuffer.prototype 是一个普通的对象,没有[[ArrayBufferData]]也没有[[ArrayBufferByteLength]]内部插槽.
  • DataView.prototype 是一个没有[[DataView]],[[ViewedArrayBuffer]],[[ByteLength]]和[[ByteOffset]]内部插槽的普通对象.
  • GeneratorFunction.prototype是一个没有[[ECMAScriptCode]]的普通对象,也不是表27表56中列出的任何其他内部插槽.
  • Promise.prototype 是一个没有[[PromiseState]]的普通对象,也不是Promise实例的任何其他内部插槽.

然而,旧的行为仍然适用于那些:

所以现在的原因是向后兼容性:

Function原型对象被指定为一个函数对象,以确保与ECMAScript 2015规范之前创建的ECMAScript代码兼容.

请注意,这不会产生Function.prototype特殊功能.只有构造函数具有以下prototype属性:

可用作构造函数的函数实例具有prototype 属性.

除了之外Function.prototype,还有许多非构造函数的例子,例如

  • javascript的母亲.当我认为它不再让我感到惊讶时 (2认同)

小智 6

在回答你的问题时:

1) Function.prototype是一种功能,因为根据ECMAScript 2015:

Function原型对象是内部对象%FunctionPrototype%.Function原型对象本身就是一个内置的函数对象.

Function原型对象被指定为一个函数对象,以确保与ECMAScript 2015规范之前创建的ECMAScript代码兼容.

因此,Function原型对象仅定义为Function对象,以确保与较旧的ECMAScript标准兼容.该函数实际上没有做任何事情:

调用时,它接受任何参数并返回undefined.

http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-prototype-object

2)关于原型属性:

Function原型对象没有prototype属性.

同源

这是唯一的,因为所有函数通常都具有prototype属性,但是由于Function原型对象仅被指定为Function对象以保持兼容性,因此它的行为与常规函数不同.

我已经创建了一个带有各种测试的JSFiddle,以防它帮助任何人:

http://jsfiddle.net/Ld0b39xz/

// We'll use 'Object.getPrototypeOf' to access [[prototype]]

// As you know, [[prototype]] of Object.prototype returns 'null'. 
console.log(Object.getPrototypeOf(Object.prototype));
// null

////////////////////////////////////////////////////////

// Let's take a closer look at Function.prototype
console.log(Function.prototype);
// Output:
// function(){}

// This is what the specs say should happen:
// "The Function prototype object is itself a built-in function object."

/////////////////////////////////////////////////////

// Let's see if this function has a 'prototype' property.
// All functions normally have a prototype property that initially
// references an empty object...except this one.
var fn = Function.prototype;
console.log(fn.prototype);
// Output:
// undefined

// This is expected, according to the specs:
// "The Function prototype object does not have a prototype property."

// It does have some properties such as 'name' and 'length',
// but not 'prototype'.

////////////////////////////////////////////////////////

// Let's see what [[prototype]] of Function.prototype returns.
console.log(Object.getPrototypeOf(Function.prototype));
// Output:
// Object{}

// Again this is expected:
// "The value of the [[Prototype]] internal slot of the
// Function prototype object is the intrinsic object %ObjectPrototype%"

/////////////////////////////////////////////////////////

// Now lets see what the [[Prototype]] of this object is:
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function.prototype)));
// Output:
// null

// We've come full circle since all the statement above is
// doing is looking for the prototoype of the native Object,
// which we already know is 'null' from our first test.
Run Code Online (Sandbox Code Playgroud)