为什么函数属性定义在对象本身上(例如Function.name),而方法定义在Function.prototype上?
Why do Function properties are defined on the object itself (e.g. Function.name), but methods - on Function.prototype?
从API定义属性如Function.name
,和方法如Function.prototype.call()
。但在代码中,我仍然以相同的方式调用它们,例如:
function Foo() {console.log("inside Foo")}
console.log(Foo.name); // Foo
Foo.call(); // inside Foo
。我只是简单地输入一个函数名(Foo),然后是我想要使用的方法/属性。那么为什么在API中,我看到Function
上定义的属性和Function.prototype
上定义的方法?
将方法放在prototype
中允许您在所有实例中共享它们,而不是为每个实例复制它们。
例如,Function.prototype.call
的行为不依赖于调用哪个函数。它只需要一个对函数的引用(通过this
参数接收),以便以后调用它。
但是,像name
这样的内部数据必须存储在函数对象本身中。它不能存储在prototype
中,因为每个函数实例都有自己的name
。它可以作为内部[[Name]]属性存储,并通过prototype
中定义的getter和setter来访问,但是数据仍然需要存储在函数中。
注意prototype
中定义了非方法属性,例如constructor
简短回答:
函数(通常)可以在实例之间共享,所以它们在prototype
中。
prototype
属性(例如方法Foo.prototype.call
)可以使用对象的实例访问,而直接属性(例如Foo.name
)可以通过对象本身(而不是其实例)访问,例如static属性。
在你的例子中,Foo.name
和Foo.prototype.call
之间有很大的区别,为了使用Foo.name
,你可以直接调用它,而为了使用Foo.prototype.call
,你需要创建一个实例,然后它就可用了
function Foo(){}
Foo.prototype.call = funciton(){console.log('I was called');}
Foo.name = 'My name is';
console.log(Foo.name); //My name is
var instance = new Foo();
instances.call(); //I was called
你需要注意的另一件事是,name
和call
在JavaScript中的Function
对象类型中都有一个本地定义-因此,当你调用Foo.call()
时,你调用Function.prototype.call
方法(就像调用Foo();
一样,有一个小的区别,在这种情况下没有影响)
对于将不可变值的默认值(或根据约定不发生变化的对象)放置在通用/预期属性的原型中,实际上存在一些争论。
属性的重新赋值将始终在"当前this"对象中(好吧,发生赋值的对象)。因此,如果属性稍后被赋值——在构造函数中甚至之后——它们将被"提升"为实际实例的属性,而不是原型1。
然而,由于差异(如果有的话)非常小,并且取决于情况,因此通常的做法是只是在构造函数中转储所有属性赋值。无论使用什么方法,每个对象的属性都需要单独设置。
在[prototype]中共享可变属性可能会受到质疑,因为该属性(当发生突变时)的行为类似于静态变量;对共享对象的修改应该非常小心。
1唯一可观察到的区别是'where'默认属性被分配,如果使用hasOwnProperty
。
有趣的相关阅读:我应该在原型上设置属性的默认值以节省空间吗?(是的,我知道这与我的第一句话不一致。)
这里你有一个小小的误解。您可以在函数本身上定义属性和函数(方法)。你可以定义你想要的属性和函数在原型上构造的对象。这不是一回事。
例如,基本Object
构造函数的.create()
方法被定义为Object.create()
,而对象实例的.hasOwnProperty()
方法被定义为Object.prototype.hasOwnProperty()
。
例如,如果从构造函数Fruit()
创建了一个对象mango
,那么:
mango.weight(); // method comes from Fruit.prototype.weight()
Fruit.isFruit(mango); // method comes from Fruit.isFruit()
具体来说,Fruit.isFruit()
里面的this
指的是函数Fruit()
,上例中Fruit.prototype.weight()
里面的this
指的是对象mango
。
如果您习惯于从其他语言进行OO编程,则静态和非静态类成员之间的区别。
- $(document).ready和jQuery(function($)不工作;jQuery已定义,但脚本尚未定义;t进
- 防止自定义文本出现在页面上的所有高图表上,←使用 {events:{load:function(){var.
- Javascript,未捕获引用错误:未定义function()
- 财产的价值'openNewWin'为null或未定义,而不是Function对象
- 对 Javascript 中未定义的 .function 进行最小条件检查
- 角度.js错误:factory.function(..) 未定义
- 定义一个扩展Function的类
- JavaScript中到底定义了什么(function(require){..})
- TypeError:调用Function.protype.method()时,this.prototype未定义
- Javascript〔remove:function〕记录自定义数组CQ-Ext-js
- 定义函数并在select语句中用作onchange,而不是直接使用.change(function)
- “function"Javascript中没有定义错误:调用函数的正确方式是什么?
- Uncaught ReferenceError: [function]没有定义
- 为什么函数属性定义在对象本身上(例如Function.name),而方法定义在Function.prototype上?
- JavaScript类定义从(function())开始
- 美元(文档).Ready (function() $未定义
- 为什么object.function.this在使用function.call时没有定义
- 为什么Function.prototype.bind() "函数中的自定义属性
- 0x800a138f - JavaScript运行时错误:属性'$'为空或未定义,不是Function对
- 为什么要检查定义的变量var m = m || function(){}