53

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

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

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

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

谢谢

4

3 回答 3

66

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

在 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

(注意:出于兼容性的原因,通常不建议扩展像Arrays 这样的原生对象的原型。但是这个特定的例子通常是一个受欢迎的补充,以及像mapforEach对于旧浏览器的规范化方法。)

永远不要扩展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"

你也可以在 s 中定义更多的函数prototype

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.body是 的一个实例HTMLBodyElement,它是 的子类HTMLElement,是 的子类,Element以此类推,直到您Object成为最上面的超类。因此,document.body继承了 、 和 的原型中定义HTMLBodyElement的所有HTMLElement方法。这称为原型链。ElementObject

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

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
于 2012-08-21T23:07:17.577 回答
6

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

于 2012-08-21T22:50:22.353 回答
4
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
于 2012-08-21T22:56:15.347 回答