复制属性继承(Inheritance by Copying Properties)

让我们看一下另一个继承模式—复制属性继承(inheritance by copying properties)。在这个模式中,一个对象从另一个对象获取功能,简单的通过复制它。
下面是函数extend()简单实现的一个例子:
function extend(parent, child) {
var i;
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
child[i] = parent[i];
}
}
return child;
}

它是一个简单实现,仅仅依次遍历parent的成员并复制它们。在这个实现中,child是可选的;如果你不传递一个已经存在的对象去扩展,那么一个新对象被创建并被返回。

var dad = {name: "Adam"};
var kid = extend(dad);
kid.name; // "Adam"

给出的这种实现就是所谓的对象的"浅复制(shallow copy)"。深度复制另一方面意味着检查你将要复制的属性是否是一个对象或者是一个数组,如果是,递归的遍历它的属性并
同样的复制它们。使用浅复制(因为对象在JavaScript中通过引用传递),如果你改变child的属性,并且这个属性碰巧是一个对象,那么你也会修改(所有的)parent。

这种情况实际上对于方法来说是更可取的(因为函数也是对象并通过引用传递),但作用在其它对象和数组的时候可能会导致意外。设想一下:
var dad = {
counts: [1, 2, 3],
reads: {
paper: true
}
};
var kid = extend(dad);
kid.counts.push(4);
dad.counts.toString(); // "1,2,3,4"
dad.reads === kid.reads; // true

现在让我们修改extend()函数实现深度复制。你要做的就是检查属性的类型是否是个对象,如果是,递归复制它的属性。

你需要的另外一个检查是对象是否是一个真正的对象或者是否是个数组。让我们使用在前面讨论过的数组检查。
那么extend()的深度拷贝版本可能看起来像这样:
function extendDeep(parent, child) {
var i, toStr = Object.prototype.toString,
astr = "[object Array]";
child = child || {};
for (i in parent) {
if (parent.hasOwnProperty(i)) {
if (typeof parent[i] === "object") {
child[i] = (toStr.call(parent[i]) === astr) ? [] : {};
extendDeep(parent[i], child[i]);
} else {
child[i] = parent[i];
}
}
}
return child;
}

现在测试新实现给我们提供给我们的真正的对象的复制,那么child对象不会修改它们的parents:

var dad = {
counts: [1, 2, 3],
reads: {
paper: true
}
};
var kid = extendDeep(dad);
kid.counts.push(4);
kid.counts.toString(); // "1,2,3,4"
dad.counts.toString(); // "1,2,3"
dad.reads === kid.reads; // false
kid.reads.paper = false;
kid.reads.web = true;
dad.reads.paper; // true

这种属性复制模式简单并且被广泛使用;比如Firebug(使用JavaScript写的Firefox扩展)有一个叫做extend()的方法实现了一个浅复制,和jQuery的extend()实现了一个深度复制。YUI3提供一个方法叫做Y.clone(),提供一个深度复制并且通过绑定函数到child对象复制函数(接下来内容会有更多的绑定)。

有价值的是在这种模式中压根就没有原型(prototype),仅关系到对象和它们的属性。

最新文章

  1. Finite State Machine 是什么?
  2. JS自动格式化输入的数字/千位分隔符
  3. Javascript软键盘设计
  4. C调Lua
  5. Leetcode 210 Course Schedule II
  6. Mysql中的DQL查询语句
  7. Qemu对x86静态内存布局的模拟
  8. aspnet5安装ef7备忘
  9. Spring 框架原理
  10. Jenkins结合.net平台综合应用之通过SSH方式拉取代码
  11. html5 css练习 画廊 元素旋转
  12. BZOJ2219 数论之神 数论 中国剩余定理 原根 BSGS
  13. 20145203盖泽双 《网络对抗技术》实践1—— MAL_逆向与Bof基础
  14. Scala常用命令
  15. Python获取系统音量
  16. 667. Beautiful Arrangement II
  17. PHP 权威代码风格规范
  18. Java Tomcat 启动闪屏-原因之一---配置问题
  19. 转载(web app变革之rem)
  20. 【转】Google的2012论文

热门文章

  1. php __clone实现
  2. CentOS安装Nginx,并配置nodejs反向代理
  3. Altium Designer 导出Gerber文件详细教程
  4. rsyslog 解决日志截断不读取问题
  5. 安装与使用smarty
  6. 【转】secureCRT使用退格键(backspace)出现^H解决办法
  7. Android调用系统相机和文件浏览器
  8. hdu1693:eat trees(插头dp)
  9. lua面向对象封装及元表(metatable)性能测试
  10. iOS UIView指定显示摸一个角弧形显示