Javascript中的原型关键字

时间:2012-08-21 22:44:10

标签: javascript html5

什么是prototype财产,为什么有必要?到目前为止,我已经了解到,这为公共访问提供了对象的更多内在和私有prototype;那是对的吗?

另外,以下陈述之间的区别是什么?

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

简而言之,我需要更好地理解关键字prototype

由于

3 个答案:

答案 0 :(得分:62)

“原型”是在物体中发挥作用的东西。

在Javascript中,一切都是对象。每个对象都有一种,因此继承了那种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方法之前创建的数组。

(注意:出于兼容性原因,通常不建议扩展原始对象的原型,如Array s。但是这个特殊的例子通常是一个受欢迎的补充,以及规范化方法,如map和旧版浏览器forEach。)

(只是永远不会延伸Object.prototype!除非您不关心for...in语句,in运算符和这类情况。 )

如果要定义自己的类,如名称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 s中定义更多功能:

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的每个实例都会继承MyConstructor.prototype中定义的方法和成员,而不是函数MyConstructor中的方法和成员。

实际上还有很多话要说。对象可以是另一个类的子类,因此也继承了超类的prototype。例如,document.bodyHTMLBodyElement的一个实例,它是HTMLElement的子类,它是Element的子类,依此类推,直到获得Object作为最高级的超类。因此,document.body会继承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

答案 1 :(得分:6)

在JavaScript中,函数对象具有内置的.prototype属性。此属性的值是一个对象。如果该函数用作构造函数,则生成的实例将继承该“prototype”对象。

示例:

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属性(这是有道理的)因为只有函数对象可以用作构造函数。)

答案 2 :(得分:3)

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