Function.prototype 是一个函数
原因是ES5 规范是这样说的:
Function 原型对象本身就是一个 Function 对象(它的 [[Class]] 是“Function”),当被调用时,它接受任何参数并返回 undefined。
请注意,在 ES5 中使某个类的原型成为该类的成员是很常见的:
Object.prototype
是一个 Object 对象。Function.prototype
是一个undefined
在调用时返回的函数对象。Array.prototype
是一个空的 Array 对象。String.prototype
是一个字符串对象,其值为空字符串。Boolean.prototype
是一个布尔对象,其值为false
。Number.prototype
是一个数值对象,其值为+0
。Date.prototype
是一个 Date 对象,其 [[PrimitiveValue]] 是NaN
。RegExp.prototype
是一个 RegExp 对象,其数据属性与 的相似new RegExp()
。Error.prototype
是一个错误对象。
我认为它是标准化的,因为类的原型具有该类的内在属性,作为该类的实例。如果它看起来像一只鸭子,它应该表现得像一只鸭子。因此,在原型本身而不是在实例上调用原型的方法也应该有效。
然而,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.prototype
本身是一个内置函数对象。Array.prototype
是一个 Array 奇异对象,并具有为此类对象指定的内部方法。
所以现在的原因是向后兼容:
函数原型对象被指定为函数对象,以确保与 ECMAScript 2015 规范之前创建的 ECMAScript 代码兼容。
请注意,这不会产生Function.prototype
特殊功能。只有构造函数具有以下prototype
属性:
可用作构造函数的函数实例具有
prototype
属性。
除了 之外Function.prototype
,还有多个非构造函数的例子,例如
Math
对象中的方法:typeof Math.pow; // "function 'prototype' in Math.pow; // false
一些宿主对象:
typeof document.createElement('object'); // "function 'prototype' in document.createElement('object'); // false
在 ES6 中,箭头函数:
typeof (x => x * x); // "function 'prototype' in (x => x * x); // false
回答您的问题:
1) Function.prototype
是一种函数,因为根据 ECMAScript 2015:
函数原型对象是内在对象 %FunctionPrototype%。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
属性,但是由于 Function 原型对象仅被指定为 Function 对象以保持兼容性,因此它的行为与常规函数的行为不同。
我创建了一个带有各种测试的 JSFiddle,以防它对任何人有帮助:
// 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.
代替我无法忍受的先前答案。感谢 Oriol。挠头是我的。
关于第一个问题,Function 对象并没有特别不同,因为它Function.prototype
是一个函数。其他内置构造函数使用它们自己类型的原型对象。引起注意 Function 情况的是,typeof
运算符通过返回“function”而不是“object”来区别对待其他对象的函数对象。
全局构造函数将自己列为其原型对象的构造函数:
var BuiltIn = Function; // for example
BuiltIn.prototype.constructor == BuiltIn // true
或多或少是纪录片。内置构造函数的原型对象通常具有与 javascript 引擎接口的方法,并且不是使用在运行时出现的对其列出的构造函数的 javascript 调用创建的:Function.prototype instanceof Function
对于其他内置构造函数(如 Array、RegExp 等),结果为 false测试。
Function
然而,全局对象是独一无二的,因为它将自己列为自己的构造函数(Function.constructor == Function
为真),并且它是自身的一个实例(Function instanceof Function
也为真)。后一个结果表明Function.prototype
在 的原型链中Function
。 Function.prototype
本身是原型Object.prototype
。
另一个考虑Function.prototype
不是通常意义上的 Function 对象的原因(除了在文档中这样说)是它不能作为构造函数调用,并且如果尝试这样做会抛出错误。由于在函数作为构造函数调用时会使用函数的原型属性,因此Function.prototype
不具有此属性是有意义的。