Javascript中的原型关键字

什么是prototype属性,为什么它是必要的? 到目前为止,我已经知道,这为公众提供了更多内在的,私人的对象prototype ; 那是对的吗?

另外,下面的陈述有什么区别?

 MyConstructor.age = 30; MyConstructor.prototype.age = 30; 

总之,我需要更好地了解关键字prototype

谢谢

“原型”是在对象中起作用的东西。

在Javascript中,一切都是一个对象。 每个对象都有一种types,从而inheritance了这种types的prototype

例如,取一个简单的数组: var a = [] 。 你可以用它来操作,比如a.push(10)push方法从哪里来? 从Array对象的原型来看,哪a是。

您可以将自己的方法添加到Array对象,只需在prototype对象中定义它们即可。 例如:

 Array.prototype.sortNum = function() {this.sort(function(a, b) {return a - b});}; 

通过这种方式,您可以对所有数组执行类似于a.sortNum() ,甚至可以在定义sortNum方法之前创build数组。

(注意:出于兼容性原因,通常不build议扩展像Array这样的本地对象的原型,但是这个特殊的例子通常是一个值得欢迎的例子,同时也为像老版本的浏览器的mapforEach这样的标准化方法。

(只要永远不要扩展Object.prototype !除非你不在乎在for...in声明中, in运算符和这些types的情况下搞砸了。)

如果你想定义你自己的类,比如MyConstructor的名字,你必须定义它的prototype来定义这个类的所有实例的方法:

 function MyConstructor(name) {this.name = name}; MyConstructor.prototype = { print: function() {return this.name;} }; var mc = new MyConstructor("foo"); alert(mc.print()); // alerts "foo" 

您也可以在prototype定义更多的function:

 MyConstructor.prototype.age = 30; alert(mc.age); // alerts 30 

当你这样做的时候要注意定义“默认”对象值,因为改变它可能会导致该类的所有实例发生变化。

但是这与Object.defineProperty方便:

 Object.defineProperty(MyConstructor.prototype, "wholeString", { get: function() {return this.name + "=" + this.age;}, set: function(v) {this.name = v.substring(3);} }); alert(mc.wholeString); // alerts "foo = 30" 

(不幸的是,IE <9只允许这个DOM对象…)

当你定义MyConstructor.age = 30 ,你实际上在做的是定义MyConstructor 函数的一个成员,所以mc.age将是未定义的。 MyConstructor每个实例都inheritanceMyConstructor.prototype定义的方法和成员,而不是函数MyConstructor的方法和成员。

实际上还有很多要说的。 对象可以是另一个类的子类,因此也inheritance了超类的prototype 。 例如, document.bodyHTMLBodyElement一个实例,它是HTMLElement一个子类,它是Element一个子类,等等,直到你把Object作为最上层的超类。 所以, document.bodyinheritance了HTMLBodyElementHTMLElementElementObject原型中定义的所有方法。 这被称为原型链。

对自定义对象做同样的事情有点棘手:

 function Class() {}; Class.prototype.foo = function() {alert("foo");}; function Subclass() {}; Subclass.prototype = new Class(); Subclass.prototype.bar = function() {alert("bar");}; var a = new Class(), b = new Subclass(); a.foo(); // alerts"foo" a.bar(); // throws an error b.foo(); // alerts "foo" b.bar(); // alerts "bar" a instanceof Class; // true a instanceof Subclass; // false b instanceof Class; // true b instanceof Subclass; // true 

在JavaScript中,函数对象具有内置的.prototype属性。 这个属性的值是一个对象。 如果该函数被用作构造函数,那么结果实例将inheritance该“原型”对象。

例:

 var Dog = function () {}; // the constructor function Dog.prototype.bark = function () {}; // adding a method to Dog.prototype var dog1 = new Dog; // creating a new instance dog1.bark(); // the instance inherits the "bark" method from Dog.prototype 

请注意,函数对象的.prototype属性与[[Prototype]]内部属性不同。 所有对象都包含后者。 这是一个对象原型的内部引用。 (在上面的例子中, dog1对象的[[Prototype]]指的是Dog.prototype 。)另一方面,只有函数对象具有内置的.prototype属性(这是有道理的,因为只有函数对象可以用作构造函数)。

 var foo = function () {}; foo.bar = 5; foo.prototype.foobar = 10; var x = new foo(); x.bar; // undefined x.foobar; // 10 

编辑:另外,你可以做

 foo.prototype.foobar = 20; x.foobar; // 20