日期:2014-05-16  浏览次数:20358 次

js原型模式创建对象+动态原型模式的优点

原型模式创建对象也有自己的缺点 , 它省略了构造函数传参初始化这一过程 , 带来的缺点就是初始化的值都是一致的。而原型最大的缺点就是它最大的优点,那就是共享。
原型中所有属性是被很多实例共享的 , 共享对于函数非常合适 , 对于包含基本值的属性也还可以。但如果属性包含引用类型,就存在一定的问题:

function Box() {};
Box.prototype = {
constructor : Box,
name : 'Lee',
age : 100,
family : [' 父亲 ', ' 母亲 ', ' 妹妹 '], // 添加了一个数组属性
run : function () {
return this.name + this.age + this.family;
}
};
var box1 = new Box();
box1.family.push(' 哥哥 '); // 在实例中添加 ' 哥哥 '
alert(box1.run());
var box2 = new Box();
alert(box 2 .run()); // 共享带来的麻烦,也有 ' 哥哥 ' 了


PS :数据共享的缘故,导致很多开发者放弃使用原型,因为每次实例化出的数据需要
保留自己的特性,而不能共享。


为了解决构造传参和共享问题,可以 组合构造函数 +? 原型模式 :
function Box(name, age) { // 不共享的使用构造函数
this.name = name;
this.age = age;
this. family = [' 父亲 ', ' 母亲 ', ' 妹妹 '];
};
Box.prototype = { // 共享的使用原型模式
constructor : Box,
run : function () {
return this.name + this.age + this.family;
}
};


PS : 这种混合模式很好的解决了传参和引用共享的大难题 。 是创建对象比较好的方法 。

?

?

原型模式 , 不管你是否调用了原型中的共享方法 , 它都会初始化原型中的方法 , 并且在
声明一个对象时 , 构造函数 + 原型部分让人感觉又很怪异 , 最好就是把构造函数和原型封装
到一起。为了解决这个问题,我们可以使用 动态原型模式 。


function Box(name ,age) { // 将所有信息封装到函数体内
this.name = name;
this.age = age;
if (typeof this.run != 'function') { // 仅在第一次调用的初始化
Box.prototype.run = function () {
return this.name + this.age + ' 运行中 ...';
};
}
}
var box = new Box('Lee', 100);
alert(box.run());


当第一次调用构造函数时, run() 方法发现不存在,然后初始化原型。当第二次调用 , 就
不会初始化 , 并且第二次创建新对象 , 原型也不会再初始化了 。 这样及得到了封装 , 又实现
了原型方法共享,并且属性都保持独立。

?

?