【问题标题】:Why do built-in functions not have a prototype property?为什么内置函数没有原型属性?
【发布时间】:2013-01-05 06:42:47
【问题描述】:

鉴于 ES 5.1 标准规定...

1)http://es5.github.com/#x13.2脚下的注释

NOTE A prototype property is automatically created for every function,
to allow for the possibility that the function will be used as a constructor.

2)http://es5.github.com/#x15.3.5.2

NOTE Function objects created using Function.prototype.bind do not have
a prototype property.

(这意味着所有其他功能都可以)

...为什么内置函数不再有原型属性?:

[].push.prototype; //undefined
Math.max.prototype; //undefined

此外,即使为它们分配了原型属性,这些内置函数也不能用作构造函数:

[].push.prototype = {};
[].push.prototype; //[object Object]
new [].push(); //TypeError: function push() { [native code] } is not a constructor

相反,从用户定义的对象中删除原型属性仍然允许它用作构造函数,并且实际上将通用对象分配给生成的实例的 [[prototype]]:

var A = function() {};
A.prototype = undefined;
A.prototype; //undefined
(new A()).__proto__; //[object Object]

现在内置函数的子类型是构造函数还是函数?

[在大多数现代浏览器中测试]

【问题讨论】:

  • 这可能是因为它们是用非javascript代码实现的,因此可能没有prototype。这纯属猜测。
  • "此外,即使为它们分配了原型属性,这些内置函数也不能用作构造函数:" -- 现在这行让我感兴趣了
  • @SnakesandCoffee 好主意;但是,我看不出本机函数不能成为构造函数的原因。毕竟,new console.log(Chrome 原生)会抛出 illegal invocation,而不是 not a constructor。此外,Array 是原生的(在 chrome 中),但它可以作为构造函数调用(很容易)。
  • 这可能是因为他们不希望内置函数被篡改。存在更多可能的安全风险。
  • "not a constructor" 通常在尝试的构造函数不是函数(但 [].push 是)时抛出。

标签: javascript ecmascript-5


【解决方案1】:

不是.prototype 允许将函数用作构造函数,而是[[Construct]] 内部方法的存在。请参阅this section,第 4 步。

由用户脚本创建的普通函数自动具有此内部属性集,因此所有用户函数都可以作为构造函数调用。这是因为解释器无法知道用户打算如何使用该方法。

对于本机函数,预期用途是预先知道的,因此 javascript 引擎可以决定哪些本机函数可以作为构造函数调用。调用new [].push有意义吗?

introductory part to built-in objects中提到:

除非在特定函数的描述中另有说明,否则本节中描述的不是构造函数的内置函数都不应实现 [[Construct]] 内部方法。除非在特定函数的描述中另有说明,否则本节中描述的内置函数都不应具有原型属性。

恕我直言,原因是没有有效的实际用例需要它。没有很好的解释为什么push 应该是可实例化的:新的push 和新的通用对象有什么区别?因此,允许这些函数的实例化不会给开发人员带来任何价值,但它会从其他阅读代码的人那里得到很多WTFs

【讨论】:

  • " 调用新的[].push 有意义吗?" - 我的问题是 - 有没有理由阻止它? 为什么他们没有设置[[Construct]]
  • 是的,更少的 WTF。 push 的实例会做什么?
  • var o={}; [].push.call(o); return o一样。
  • 请注意:使函数不可构造的能力将在 ES6 中通过代理在一定程度上提供,代理可以区分构造和调用操​​作。此外,直接修改用户函数的构造和调用操​​作的能力已经被讨论为 ES7 的一种可能性:mail.mozilla.org/pipermail/es-discuss/2012-October/025465.html——这意味着这可能不再只是只有 ES 内置函数才能做到的魔法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多