7

以下程序的正确输出是什么(根据 ECMA 标准是正确的)?

function nl(x) { document.write(x + "<br>"); }
nl(Function.prototype);
nl(Function.prototype.prototype);
nl(Function.prototype.prototype == Object.prototype);
nl(Function.prototype.prototype.prototype);

Chrome 和 IE6 一致表示:

function Empty() {}
null for Chrome / undefined for IE6
false

然后崩溃。

Mozilla 输出:

function () { }
[object Object]
false
undefined

这些都是正确的吗?似乎 Mozilla 做得更好,但最好的输出是

function () { }
[object Object]
true
undefined
4

4 回答 4

12

函数原型

来自ECMAScript 语言规范

15.3.3.1 函数原型

Function.prototype 的初始值是 Function 原型对象(第 15.3.4 节)。

15.3.4 函数原型对象的属性

Function 原型对象本身就是一个 Function 对象(它的 [[Class]] 是“Function”),当被调用时,它接受任何参数并返回 undefined。Function 原型对象的内部 [[Prototype]] 属性的值是 Object 原型对象(第 15.3.2.1 节)。

它是一个“空体”的函数;如果调用它,它只会返回 undefined。Function 原型对象没有自己的 valueOf 属性;但是,它从 Object 原型 Object 继承 valueOf 属性。

我得到这个输出:

  • Opera: function () { [本机代码] }
  • 铬:函数空(){}
  • IE7:函数原型(){[本机代码]}
  • FF3:函数(){}

Chrome 和 IE7 已经命名了它们的功能,Opera 和 IE7 告诉你它不会透露实现。他们都同意这一点:

nl(typeof Function.prototype); //function

将此与以下内容进行比较:

nl(typeof Object.prototype); //object
nl(typeof Array.prototype); //object
nl(typeof String.prototype); // object

Function.prototype.prototype

我从 Opera 和 IE7获得undefined ,从 Chrome获得null ,从 FF3获得[object Object] 。谁是对的?既然“函数原型对象本身就是一个函数对象”,它不应该是对自身的循环引用吗?为了避免循环引用,他们选择了不同的方式。我不知道是否有标准或者是否取决于实现,但我认为 Object 是正确的。顺便说一句,在这里您可以看到内部 [[prototype]] 和公共原型之间的区别,就像您在之前的问题中所问的那样!

Function.prototype.prototype == Object.prototype

这是错误的,因为它不是同一个对象。往上看。

Function.prototype.prototype.prototype

只有 FF 会给你一个答案,因为他们的 Function.prototype.prototype 实现返回一个对象。

我同意您提出的输出看起来更合乎逻辑。

他们确实同意这一点:

nl(Object.prototype); // [object Object]
nl(Object.prototype.prototype); // undefined
于 2008-12-20T13:01:00.073 回答
9

您在这里所做的并不是真正走原型链 -这个问题可能会帮助您了解实际发生的情况。我没有费心检查 ECMA 规范,但这是我对这个问题的看法:

  • 函数是函数对象的构造函数

  • Function.prototype是所有函数对象继承的原型——它可能包含所有Function实例共有的属性,如callapply ;您检查的实现是一致的,因为它本身是作为函数对象实现的(正如一些人指出的那样,ECMA 规范要求这样做)

  • Function.prototype.prototype并没有多大意义,但由于Function.prototype是作为函数对象实现的(可能用作构造函数),它至少应该存在;使用Function.prototype作为构造函数创建的对象将继承其属性 - 但由于不应该做这样疯狂的事情,将其设置为nullundefined或空对象是合理的

  • Function.prototype.prototype.prototype很可能是undefined:正如我们之前所见,Function.prototype.prototype应该是没有属性的东西(nullundefined或空对象),并且绝对不是函数对象;因此,它的原型属性应该是未定义的,甚至在尝试访问时可能会抛出错误

希望这可以帮助 ;)

于 2008-12-20T14:31:10.390 回答
4

直接回答您的问题:Mozilla 是对的。不仅因为 Brendan Eich 为 Mozilla 工作,而且因为这是唯一正确的方法。让我们来看看细节:

  • 每个构造函数都是一个函数。
  • 每个函数都有prototype用于构造对象的属性。
  • 原型是一个对象(字典)。单个对象将方法/属性委托给它们各自的原型。
  • 在函数的情况下,原型对象是特殊的——它实现了函数特定的方法和属性。此对象的类型/类未定义,也无法直接使用。
  • 这个原型对象不能是Objectnor Object.prototype

让我详细说明最后一个陈述。如果它是假的,我们可以像这样在用户代码中重新创建函数:

// we re-creating the function!

// our function constructor
var Fun = function(){ /*...*/ };

// let's chain the prototype
Fun.prototype = new Object();

// do we have a function now? let's fund out
var fun = new Fun();
console.log(fun.length);  // undefined
fun.call(null);           // fail
fun.apply({}, [1, 2, 3]); // fail
// nope

我们可以观察到new Object()它没有定义新的方法或属性,并且可以尝试Object.prototype直接使用相同的结果。

总结:函数的原型不是Object也不是Object.prototype。这是一个非常特殊的物体。这是我们无法在用户代码中重新创建函数的另一个原因。

编辑:有关原型的更多详细信息,请查看此答案

于 2008-12-20T16:34:40.017 回答
2

我知道这篇文章有点老了,但我一直在网上搜索有关此主题的信息,并认为我会发布我发现的内容。原型属性用于构造函数。它允许您分配将使用 new 关键字创建的对象的原型对象。

JavaScript 中的每个对象都有一个原型对象,但许多实现不允许您直接访问它或允许您在对象创建后设置它。在 FireFox 中,您可以通过 " __proto__" 属性访问此对象。

下面我有一个使用“ __proto__”属性的代码版本。函数原型链上的部分与您认为的应该是相匹配的。

function nl(z) { document.write(z + "<br>"); }

x = {};

nl(x["__proto__"]);
nl(x["__proto__"] === Object.prototype);

nl("");

nl(nl.prototype.constructor);
nl(nl["__proto__"].constructor);
nl(nl["__proto__"] === nl.prototype);

nl("");

nl(nl["__proto__"]);
nl(nl["__proto__"] === Function.prototype);
nl(nl["__proto__"]["__proto__"] === Object.prototype);
nl(nl["__proto__"]["__proto__"]["__proto__"]);

nl("");

nl(Function["__proto__"]);
nl(Function["__proto__"]["__proto__"]);
nl(Function["__proto__"]["__proto__"] === Object.prototype);
nl(Function["__proto__"]["__proto__"]["__proto__"]);

Firefox 中的输出为:

[object Object]
true

function nl(z) { document.write(z + "
"); }
function Function() { [native code] }
false

function () { }
true
true
null

function () { }
[object Object]
true
null
于 2010-01-22T06:28:19.087 回答