JavaScript:函数原型.method

6

我猜大多数人都看过以下代码片段:

Function.prototype.method = function (name, func) {
  this.prototype[name] = func;
  return this;
};

我知道这个会影响所有的函数,因为它们都是由Function对象创建的,所以它们可以访问名为“method”的方法。但是我不确定为什么Function本身也可以像下面这样访问“method”:

Function.method('test', function () {return 1;});
4个回答

8

Edorka的回答是正确的:Function本身就是它自己的构造函数(即“父级”)。

Function.constructor;  // function Function() { [native code] }

通常情况下,你 不能 做你正在做的事情。例如,以下操作是不起作用的:

f = function () {};
f.prototype.a = 5;
f.a;  // undefined

这种方法只有在使用函数作为构造函数时才有效,代码如下:
f = function () {};
f.prototype.a = 5;
g = new f();
g.a;  // 5

但是Function很奇怪,它是所有函数的构造函数,也是一个函数本身,因此它会从自己的原型中模板化其属性。因此,您可以在代码中调用Function.method()


5

因为Function本身就是一个函数:

typeof Function === 'function'
Object.getPrototypeOf(Function) === Function.prototype

你可以看到它被称为一个函数(一种间接的eval形式):

Function('return 1+2')() === 3

所有这些都在规范中定义

zerkms在上面的评论中提出了问题:

函数对象和函数原型哪个先出现?

我们必须理解,对于我们这些渺小的程序员而言,所暴露的内容与内部所表示的内容是不同的。这可以通过覆盖Array构造函数来说明(提示:在编写答案时不要尝试这样做,否则会出现很多错误):

new Array(0, 1, 2); //gives you [0, 1, 2]
Array = function () { return [4] };
new Array(0, 1, 2); //gives you [4]
//however,
[0, 1, 2] //will always give you [0, 1, 2]

这是因为规范中的一个部分(在“语义”部分稍下方):
创建新对象的结果是将Array视为表达式new Array()的标准内置构造函数。使用数组文字(或规范称之为数组初始化器),可以确保您使用内置的Array构造函数。我举这个例子有两个原因:首先,因为它很有趣;其次,为了演示我们所做的和实际所做的有所不同。回答zerkms的问题,Function对象很可能是先出现的,但那并不是第一个函数。我们无法访问该内置函数。

zerkms问道——实际上这是一个关于“先有鸡还是先有蛋”的玩笑 :-) - zerkms
1
@zerkms 当然,而且在这种情况下,鸡实际上是由一个更有感知能力的生物带给我们的。问题现在永远解决了吗? - Zirak

1
考虑以下构造函数对象:

function Person(name, age) { this.name = name; this.age = age; }

var Construct = function () { };

一个原型共享函数:
Construct.prototype.hello = function (name) { console.log("Hello " + name); };

现在,如果您从构造函数创建一个new对象,这将获取共享成员函数:
var c = new Construct();
c.hello("World");

c相同的是instanceof Construct Object,任何函数都是instanceof Functioninstanceof ObjectFunction本身是instanceof FunctionObjectConstructinstanceof Function Object,同时 Objectinstanceof Function Object
每个function语句和运算符都是原生new Function的字面量。
每个{ }字面量都是原生new Object
constructor创建的new对象获得constructor.prototype的成员。
对象可以拥有自己的任何成员,只有原型的成员才会共享。

我认为对于Function本身来说,它应该是Object的对象,因此它只会查找Object的原型而不是Function本身的。 - sunqiang.leo
@user2546240 是的。不要混淆typeof的结果。只需尝试instanceof。因为typeof是一个字符串,它不能同时表示函数和对象。instanceof更准确,因为它知道函数既是Function对象又是Object对象的实例。 - metadings

1
因为新的功能使用了Function的原型,所以Function的方法也使用了他自己的原型方法。
如果您修改了其中一个方法或属性,并且它属于“父”原型,则使用此原型的所有其他对象都将受到影响。
一些与这个奇怪主题相关的文献:http://www.packtpub.com/article/using-prototype-property-in-javascript

2
“Function”对象和“Function”原型哪个先出现? - zerkms
原型,如果对象本身无法获取方法或属性,则向其原型或原型的原型请求。 - Edorka
我认为对于“函数本身”,它应该是Object的对象,因此它只会查找Object的原型而不是函数本身。 - sunqiang.leo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接