From the 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
和方法上定义的属性?
答案 0 :(得分:1)
简短回答:
函数(通常)可以在实例之间共享,因此它们会进入prototype
。
属性是按实例进行的,所以请进入构造函数。
答案 1 :(得分:1)
在prototype
中放置方法允许您在所有实例之间共享它们,而不是为每个实例重复它们。
例如,Function.prototype.call
的行为不依赖于调用哪个函数。它只需要引用函数(通过this
参数接收)以便稍后调用它。
但是,像name
这样的内在数据必须存储在函数对象本身中。它不能存储在prototype
中,因为每个函数实例都有自己的name
。好吧,它可以存储为内部[[Name]]属性,并通过prototype
中定义的getter和setter访问,但数据仍然需要存储在函数中。
请注意,prototype
中定义了非方法属性,例如constructor
。
答案 2 :(得分:1)
实际上有一些论据可以在普通/预期属性的原型中放置不可变值的默认值(或者不按合同变异的对象)。
属性的重新分配将始终位于“当前此对象”对象中(即,发生赋值的对象)。因此,如果稍后分配属性 - 在构造函数中或甚至之后 - 它们将被“提升”为实际实例的属性而不是原型 1 。
但是,由于差异(如果有的话)是非常适度的,并且取决于情况,所以常规练习只是转储构造函数中的所有属性赋值。无论采用何种方法,都需要单独设置每个对象的属性。
在[prototype]中共享 mutable 属性会有问题,因为属性(当变异时)的行为类似于静态变量;应始终谨慎地改变共享对象。
1 关于“在何处”分配默认属性的唯一可观察差异是使用hasOwnProperty
。
有趣的相关内容:Should I put default values of attributes on the prototype to save space?(是的,我知道这不同意我的第一句话。)
答案 3 :(得分:1)
你在这里有一点误解。您可以在函数本身上定义属性和函数(方法)。您可以定义希望函数在原型上构造的对象的属性和函数。这不是一回事。
例如,基础.create()
构造函数的Object
方法定义为Object.create()
,但对象实例的.hasOwnProperty()
方法定义为Object.prototype.hasOwnProperty()
例如,如果您有一个从构造函数mango
创建的对象Fruit()
,那么:
mango.weight(); // method comes from Fruit.prototype.weight()
Fruit.isFruit(mango); // method comes from Fruit.isFruit()
特别是,this
内的Fruit.isFruit()
引用了函数Fruit()
,而上例中this
内的Fruit.prototype.weight()
引用了对象{{} 1}}。
如果您习惯使用其他语言进行OO编程,则静态类和非静态类成员之间存在差异。
答案 4 :(得分:1)
HTTP request
属性(例如方法prototype
),而直接属性(例如Foo.prototype.call
)可通过对象本身(而不是它的实例),如 static 属性。
在您的示例中,Foo.name
和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
在JavaScript中的call
对象类型中都有一个原生定义 - 因此当您致电Function
时 - 您调用Foo.call()
方法(就像调用Function.prototype.call
一样,只有一个小的区别,在这种情况下不会影响)