函数和 Function.prototype 之间的区别

Difference between Function and Function.prototype

根据this,函数依次继承自FunctionFunctionFunction.prototype

The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype.

Function.prototype有什么意义呢?为什么不把它的属性移到 Function 而让 Function.prototype 变成 undefined?函数将从 Function 派生。

Object 等也是如此

原型上的函数只创建一次并在每个实例之间共享。在构造函数中创建的函数被创建为每个使用构造函数创建的新对象的新对象。

作为一般规则,函数应该在原型上,因为它们通常不会针对同一类型的不同对象进行修改,这有一点 memory/performance 好处。其他属性如对象和数组应该在构造函数中定义,除非你想创建一个共享的、静态的属性,在这种情况下你应该使用原型。

与普通对象或数组的区别比与函数的区别更容易看出

function Foo(){
  this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //[]
as opposed to:

function Foo(){
}

Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();

fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]

functions inherit from Function

你引用的 MDN 不严谨。它实际上说的是:

function objects inherit from Function.prototype

注意在MDN页面上,上面句子中的第一个单词"function"是大写的,但只是因为它在句子的开头,并不是因为它指的是JS对象Function。它指的是声明为 function() { }.

的常规旧函数

请记住,MDN 是由凡人编写的。我宁愿他们不使用 "inherit" 和 "inheritance",更不用说 "derived"。 JS没有严格意义上的继承这个概念。如果你使用这个术语,你最终会把自己弄糊涂。 JS 拥有的是与对象关联的原型。当访问对象上的 属性 时,如果没有找到,则查询原型。如果在那里找不到,因为原型也是具有原型的对象,所以会查询原型的原型,依此类推。

所以上面这句话最好写成"function objects have as their prototype Function.prototype".

JS Function 对象与 Function.prototype 没有直接关联,除了 Function.prototypeFunction 的 属性,并且,因为 Function 对象本身就是一个函数,它本身就有 Function.prototype 作为它的原型。 Function 上可能存在或不存在的任何属性,或由您挂在其上的任何属性,都与原型链无关,也不是任何人 "inherited"。

当您执行 (function() { }).call() 时,首先会在函数对象本身上查找 call property/method;如果它在那里不存在(通常不存在),则在声明函数时固有分配的原型上查找它,即 Function.prototype。如果不在 Function.prototype 上,您还会将 callapply 等方法放在哪里?除了 Function.prototype 之外,您还会将自动分配给函数的原型称为什么?

顺便说一句,请注意 Function.call 将正确解析为内部 call 函数。为什么?不是因为那是 call 所在的地方,也不是因为那是常规函数 "inherit" call 的地方,而是因为,因为正如我之前提到的,Function 本身就是一个函数, 因此有原型 Function.prototype, call 可以在其原型链上找到.

What's the point of Function.prototype then? Why not move its properties to Function and let Function.prototype be undefined? Functions would be derived from Function instead.

X.prototype 是 X 上的 属性,用作使用 X 作为构造函数创建的对象的原型。因此,要将正确的原型分配给使用 Function 作为构造函数创建的对象(包括声明为 function x() { } 的函数),原型必须作为 prototype 属性 Function.

如果你想扩展功能,你需要 Function.prototype,考虑这个:

Function.prototype.moo = 5;
function x() { };
console.log(x.moo); // 5

您创建的每个函数现在都有 属性 moo,对比:

Function.quack = 6;
function b() {};
console.log(b.quack); // undefined

如果您只是将 属性 打到 Function 上,则情况并非如此。每个函数都不会继承分配给 Function 的属性,这就是为什么你需要 Function.prototype.