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

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在这里被当作源对象。
原型代理与原型克隆间主要的不同之处在于,原型克隆中的实例属性都是经过拷贝的,而原型代理在不同实例间只共享一份属性拷贝,在你对实例属性进行重写前,外界访问到的永远是原型中所设置的属性值。如此看来,原型代理对内存的消耗更少。
在实际应用中,为了创建各个实例间的共有方法与私有属性,常常将这两种方法混合使用。

时间: 2025-01-25 17:20:48

《JavaScript应用程序设计》一一3.5 原型克隆的相关文章

JavaScript高级程序设计 扩展--关于动态原型_javascript技巧

但是作者Nicholas C. Zakas在[动态原型]方式创建对象的时候没有深究可能会存在的问题和解决方案.而仅仅在继承的时候对[动态原型]的瓶颈作了说明.即在作子类继承的时候,不能通过动态原型的方式来实现. 原文大致如下: 继承机制不能采用动态化的原因是:prototype对象的唯一性.实例代码: 复制代码 代码如下: function A (i) { this.a = i; if (typeof A._init == 'undefined') { A.prototype.func = fu

《JavaScript应用程序设计》一一3.3 原型

3.3 原型 原型让你能够对现有对象克隆,从而构建出一个拥有其范性方法的代理对象.工厂函数在JavaScript中,有许多灵活且简单的构造函数,所有JavaScript中的函数均可以返回对象,所以你无需再使用构造函数去构建对象.相较于构造函数,工厂函数不仅为调用者封装了对象实例化的细节,而且省略了多余的new关键字.在工厂函数中,可以组合使用JavaScript的所有语言特性,甚至能够在程序运行期间,动态修改对象的构建逻辑(而且丝毫不影响正在实例化的对象).流式API(不要与流式JavaScri

《JavaScript应用程序设计》一一第3章 对象

第3章 对象JavaScript拥有原型继承.动态对象扩展.闭包等特性,在现今市面上流行的所有编程语言中,基于对象编程的JavaScript最具灵活性与表现力.在JavaScript中,你可以将诸如函数.数组.键/值对以及一些基础数据结构都视为对象,甚至一些原始数据类型在用点语法做属性操作时,也会被JavaScript隐式当作对象处理.为了能够调用原型链上的方法,原始数据类型在使用时会被临时包裹为对象,例如:'tonya@example.com'.split('@')[1]; // => exa

javascript组合使用构造函数模式和原型模式实例

  本文实例讲述了javascript组合使用构造函数模式和原型模式的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function testPrototype2(){ function Person3(name, age, job){ this.name=name; this.age=age; this.job=job; this.friends =["shelb", "

JavaScript高级程序设计(第3版)学习笔记8 js函数(中)_基础知识

6.执行环境和作用域 (1)执行环境(execution context):所有的JavaScript代码都运行在一个执行环境中,当控制权转移至JavaScript的可执行代码时,就进入了一个执行环境.活动的执行环境从逻辑上形成了一个栈,全局执行环境永远是这个栈的栈底元素,栈顶元素就是当前正在运行的执行环境.每一个函数都有自己的执行环境,当执行流进入一个函数时,会将这个函数的执行环境压入栈顶,函数执行完之后再将这个执行环境弹出,控制权返回给之前的执行环境. (2)变量对象(variable ob

JavaScript高级程序设计(第3版)学习笔记6 初识js对象_基础知识

在房子里面可以放你想放的任意事物--如果你有足够的美学造诣,你甚至可以弄一个房中房试试--当然,为了方便管理,我们会给房子里存放的所有事物都会取上一个不重复的名字,比如医药房间里的各种药品名称.在ECMAScript中,你可以在对象中存放任意你想放的数据,同样,我们需要给存放的数据取一个名字--也就是对象的属性名,再存放各种数据.再看看ECMA-262中对象的定义:无序属性的集合,其属性可以包含简单数据类型值.对象或者函数. 进入对象,我开始有些激动了,说实话,让我想起做这系列学习笔记的最初原因

《JavaScript应用程序设计》导读

前言 在本书中我们先后提到了不少Web开发类书籍,但对于那些想从头开始学习构建完整JavaScript应用的读者来说,市面上真正值得推荐的JavaScript教程又显得十分稀缺.与此同时,现在几乎每一个互联网创业公司的人员配备中都少不了资深JavaScript应用程序开发者的角色.本书旨在帮助人们了解如何构建易于扩展和维护的完整JavaScript应用. 本书并不打算向读者详细讲解JavaScript语言基础,它基于你现有的JavaScript知识结构,向你展示那些会让你的编码工作长久受益的Ja

《JavaScript高级程序设计》学习笔记

系统学习JS, 从<JavaScript高级程序设计>入门,通过学习jQuery或者angularJS源码来进阶. 第1章 JavaScript简介 1.JS问世的目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作, 由Netscape主导开发,那时候微软的IE还不能独领风骚.最初叫做LiveScript,当时媒体热炒Java,于是改名为JavaScript. JavaScript和ECMAScript通常指同一门语言,但是,JavaScript是ECMA-262标准的实现和扩展

举例说明JavaScript中的实例对象与原型对象_基础知识

首先声明:javascript中每个对象都有一个constructor属性和一个prototype属性.constructor指向对象的构造函数,prototype指向使用构造函数创建的对象实例的原型对象. function Person(){ } var person = new Person(); Person.prototype = { constructor : Person, name : 'zxs', age : 24, sayName : function(){alert(this