《JavaScript应用程序设计》一一3.5 原型克隆

本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第3章,第3.5节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.5 原型克隆

有时你并不希望在原型上做数据共享,相反,你想让每个实例都拥有一份属于自己的原型拷贝。多数主流JavaScript类库中早已经存在了一个用来对原型进行克隆的方法,以extend()方法最为常见,它首先被传入一个待扩展的对象,之后所传入的所有对象都是对第一个对象的扩展。
不过extend()方法并没有出现在JavaScript规范中(尽管ES6规范中定义的Object.assign()方法与extend()方法十分相似), 在jQuery与Underscore中可以找到它的身影,它的实现也极为简单。下面的代码摘自Underscore。

_.extend = function(obj) {
      each(slice.call(arguments, 1), function(source) {
        for (var prop in source) {
          obj[prop] = source[prop];
        }
      });
      return obj;
    };

如你所见,它将第一个入参作为目标对象,随后遍历剩余的入参,将剩余入参对象中的公共属性逐一拷贝至目标对象。当多个对象上的同名属性值存在冲突时,永远是后一个优先覆盖前一个。
来看看如何使用extend()方法来进行原型克隆:

var switchProto = {
      isOn: function isOn() {
        return this.state;
      },

      toggle: function toggle() {
        this.state = !this.state;
        return this;
      },

      meta: {
        name: 'Light switch'
      },

      state: false
    },

    switch1 = extend({}, switchProto),
    switch2 = extend({}, switchProto);

  test('Prototype clones.', function () {

    switch1.isOn.isShared = true;

    ok(!switch2.isShared, 
      'Methods are copied for each instance, not shared.'
    );

    ok(switch1.toggle().isOn(),
      '.toggle() works.'
    );

    ok(!switch2.isOn(),
      'instance safe.'
    );

    switch2.meta.name = 'Breaker switch';

    equal(switch1.meta.name, 'Breaker switch',
      'Object and array mutations are shared.'
    );

    switch2.meta = { name: 'Power switch' };

    equal(switch1.meta.name, 'Breaker switch',
      'Property replacement is instance-specific.'
    );
  });

在上述示例的extend()方法调用中,我们传入了一个空对象字面量作为目标对象,switchProto在这里被当作源对象。
原型代理与原型克隆间主要的不同之处在于,原型克隆中的实例属性都是经过拷贝的,而原型代理在不同实例间只共享一份属性拷贝,在你对实例属性进行重写前,外界访问到的永远是原型中所设置的属性值。如此看来,原型代理对内存的消耗更少。
在实际应用中,为了创建各个实例间的共有方法与私有属性,常常将这两种方法混合使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值