3

我一直在尝试理解 JS 中原型的概念,但由于某种原因,我发现它真的很莫名其妙。为什么以及何时使用原型?

这之间有什么区别(来自这个MDN 示例):

function Person(gender) {
  this.gender = gender;
}

Person.prototype.sayHello = function()
{
  alert ('hello');
};

还有这个:

function Person(gender) {
  this.gender = gender;

  this.sayHello = function() {
    alert('hello');
  };
}

我想我了解如何使用它们,但我不知道为什么要使用它们。也许我错过了一些东西 - 从头开始​​ - 显然我错过了一些东西!

有人可以解释这两个示例之间的区别以及为什么我应该使用另一个示例吗?

谢谢!

4

4 回答 4

1

当您new Person()使用原型示例创建一个时,它不会sayHello()与 person 对象一起加载到内存中。

相反,它会在需要/调用时立即将其添加到对象中,并且仅在需要时加载一次。

在处理大量对象时,这可以为用户节省大量内存。

于 2013-04-03T20:43:03.667 回答
1

类和继承。我强烈建议您阅读这个小教程,而不是花一两个小时自己解释。我跳过它到原型部分,它以一种有趣的方式很好地解释了它。

于 2013-04-03T20:48:52.153 回答
1

Person是一个构造函数,每次创建新实例时都会执行。构造函数只是函数,函数只是 JavaScript 中的对象。函数可以有属性f.a = 1,就像基本对象一样:o = {a: 1}.

当您将函数添加为对象的属性时,它被称为方法。因此,通过Person在构造函数中定义方法,它们会在实例化时重新定义。正如已经指出的,这是额外的工作。

通过使用prototype函数的属性预先定义方法,方法只定义一次。

在原型上定义方法的另一个好处是它们变成静态的。静态方法不需要实例对象。例如,可以在数组实例上调用数组切片方法:[1,2,3].slice(1). 但是如果我们没有数组实例,我们仍然可以从 Array 对象的原型中访问和调用 slice 方法:Array.prototype.slice.call(arguments)

编辑:静态方法通常被视为Object.method,不一定是原型的属性。应该澄清的是,实例方法.slice()是静态调用的。

于 2013-04-03T20:57:28.043 回答
1

原型对于继承很重要。如果你不需要继承,那么真的没有区别。但是,考虑一下:

function Person(gender) {
 this.gender = gender;

 this.sayHello = function() {
  alert('hello');
 };
}

function User(){

}

一个怎么可能User是一个Person?这里真的没有简单的方法。但是,这可以通过原型实现:

jsFiddle 演示

function Person(name) {
 this.name = name;
}

Person.prototype.sayHello = function() {
  alert(this.name);
 };

function User(name){
 this.constructor(name);
}

User.prototype = new Person();

var u = new User("joe");
u.sayHello();//alerts joe

现在,我们可以更进一步,在使用这样的原型时覆盖向用户问好的功能:

jsFiddle 演示

User.prototype.sayHello = function(){ 
 alert("Username: " + this.name);
}
于 2013-04-03T21:24:25.603 回答