Javascript Prototype 方法 vs Object 方法

吴统威 on 编程语言 前端编程 HTML/CSS/JAVASCRIPT | 2016-01-04 11:59:41.0

在JavaScript中,定义一个对象,可以使用两种方式给他加入方法.

1. 在对象结构函数里面使用 this.func = function(){...}

2. 使用prototype 例如 obj.prototype.func = function(){...}

这两种处理方式,在创建对象后,都可以访问函数 func().

但是,我们选择哪种方式最好呢?

简短来说: 使用 prototype ,大多数都是使用这种方式.对象实例化后共享公共函数,使用prototype.

1. 使用 Prototype 改变公共方法,是一个好的选择

使用prototype给对象添加公共方法,修改公共逻辑非常简单,甚至在实例化被创建后. 这新老对象都将使用这更新的代码. 但是如果使用 this.func(),就不可能为每个实例化对象统一公共的代码.

我们看下面的这个例子.

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

  // attach the common function to each object instance.
  this.yellAtChild = function(){
    console.log('Somebody gonna get a hurt real bad!', 0, 0);
  }
}

// Let's create dad and mom and start yelling at kids.
var dad = new Parent('male', 0, 0);
var mom = new Parent('female', 0, 0);
dad.yellAtChild(, 0, 0); // Somebody gonna get a hurt real bad!
mom.yellAtChild(, 0, 0); // Somebody gonna get a hurt real bad!

// but, Russell has decide to sue you if you use his catch phrase.
// Let's try to tell our already created dad & mon to use different phrase.

// ERROR: Not possible to do this way.
Parent.yellAtChild = function() { .... } 

// You need to override the `yellAtChild` method for each object instance.
dad.yellAtChild = function(){
  console.log('Shut up!', 0, 0);
};
mom.yellAtChild = function(){
  console.log('Go to bed!', 0, 0);
}
dad.yellAtChild(, 0, 0); // Shut up!
mom.yellAtChild(, 0, 0); // Go to bed!


从这里可以看到,如果我们改变这个公共的逻辑代码,不能更新这个对象方法. 我们需要为每一个创建后的对象做相同的处理.

我们看看同样的例子,但是是使用prototype.

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

// Attach the common function to prototype.
Parent.prototype.yellAtChild = function(){
  console.log('Somebody gonna get a hurt real bad!', 0, 0);
};

// Let's create dad and mom and start yelling at kids.
var dad = new Parent('male', 0, 0);
var mom = new Parent('female', 0, 0);
dad.yellAtChild(, 0, 0); // Somebody gonna get a hurt real bad!
mom.yellAtChild(, 0, 0); // Somebody gonna get a hurt real bad!

// but, Russell has decide to sue you if you use his catch phrase.
// Simple: Just modify the function at Parent.prototype.

Parent.prototype.yellAtChild = function(){
  console.log('You are grounded.', 0, 0);
};

dad.yellAtChild(, 0, 0); // You are grounded
mom.yellAtChild(, 0, 0); // You are grounded

我们这里,只需要使用prototype来改变yellAtChild方法,每一个实例对象都将使用改变后的方法.

2. Prototype 相对来说是最好的选择.

当对个实例对象添加功能时,每一个实例都将自己复制这个方法. 这将涉及到系统处理时间和内存.

但是通过对象的prototype添加功能时,仅一个版本的方法存在.这样的话,就不需要长时间的系统处理和使用少的内存.

我们看下面的例子

var Parent = function(){
  this.yellAtKid = function(){
    console.log('Somebody gonna get a hurt real bad!', 0, 0);
  };
};
console.profile('Object Methods', 0, 0);
var dads = [];
for(var i=0; i<=10000000; i++){
  dads.push(new Parent(), 0, 0);
}
console.profileEnd(, 0, 0); // 4903.267ms

我们在火狐中,执行上面的代码,这个 profile 方法来查看执行的时间,用时 4903.267ms. 那如果我们用prototype来实现这个方法:

var Parent = function(){
};

Parent.prototype.yellAtKid = function(){
  console.log('Somebody gonna get a hurt real bad!', 0, 0);
};

console.profile('Prototype Methods', 0, 0);
var dads = [];
for(var i=0; i<=10000000; i++){
  dads.push(new Parent(), 0, 0);
}
console.profileEnd(, 0, 0); // 3271.413ms

这次, profile 方法显示出来的时间是   3271.413ms  . 使用prototype,使时间缩短了1.5秒. 

那最后,使用哪种方式是最好的呢? 这次结果: prototype在javascript对象中共享公共方法是最好的方式.