在JavaScript中,定义一个对象,可以使用两种方式给他加入方法.
1. 在对象结构函数里面使用 this.func = function(){...}
2. 使用prototype 例如 obj.prototype.func = function(){...}
这两种处理方式,在创建对象后,都可以访问函数 func().
但是,我们选择哪种方式最好呢?
简短来说: 使用 prototype ,大多数都是使用这种方式.对象实例化后共享公共函数,使用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方法,每一个实例对象都将使用改变后的方法.
当对个实例对象添加功能时,每一个实例都将自己复制这个方法. 这将涉及到系统处理时间和内存.
但是通过对象的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对象中共享公共方法是最好的方式.