function extendCopy(p) {
var c = {}
for (var i in p) {
c[i] = p[i]
}
c.uber = p
return c
}
拷贝完成之后对于新对象中需要改写的属性可以进行手动改写。
深拷贝:
浅拷贝的问题也显而易见,它不能拷贝对象类型的属性而只能传递引用,要解决这个问题就要使用深拷贝。深拷贝的重点在于拷贝的递归调用,检测到对象类型的属性时就创建对应的对象或数组,并逐一复制其中的基本类型值。
复制代码 代码如下:
function deepCopy(p, c) {
c = c || {}
for (var i in p) {
if (p.hasOwnProperty(i)) {
if (typeof p[i] === 'object') {
c[i] = Array.isArray(p[i]) ? [] : {}
deepCopy(p[i], c[i])
} else {
c[i] = p[i]
}
}
}
return c
}
其中用到了一个 ES5 的Array.isArray()方法用于判断参数是否为数组,没有实现此方法的环境需要自己手动封装一个 shim。
复制代码 代码如下:
Array.isArray = function(p) {
return p instanceof Array
}
但是使用instanceof操作符无法判断来自不同框架的数组变量,但这种情况比较少。
6.原型继承:
借助父级对象,通过构造函数创建一个以父级对象为原型的新对象:
复制代码 代码如下:
function object(o) {
var n
function F() {}
F.prototype = o
n = new F()
n.uber = o
return n
}
这里,直接将父对象设置为子对象的原型,ES5 中的 Object.create()方法就是这种实现方式。
7.原型继承和属性拷贝混用:
原型继承方法中以传入的父对象为原型构建子对象,同时还可以在父对象提供的属性之外额外传入需要拷贝属性的对象:
复制代码 代码如下:
function ojbectPlus(o, stuff) {
var n
function F() {}
F.prototype = o
n = new F()
n.uber = o
for (var i in stuff) {
n[i] = stuff[i]
}
return n
}
8.多重继承:
这种方式不涉及原型链的操作,传入多个需要拷贝属性的对象,依次进行属性的全拷贝:
复制代码 代码如下:
function multi() {
var n = {}, stuff, i = 0,
len = arguments.length
for (i = 0; i < len; i++) {
stuff = arguments[i]
for (var key in stuff) {
n[i] = stuff[i]
}
}
return n
}
根据对象传入的顺序依次进行拷贝,也就是说,如果后传入的对象包含和前面对象相同的属性,后者将会覆盖前者。
9.构造器借用:
JavaScript中的call()和apply()方法非常好用,其改变方法执行上下文的功能在继承的实现中也能发挥作用。所谓构造器借用是指在子对象构造器中借用父对象的构造函数对this进行操作:
复制代码 代码如下:
function Parent() {}
Parent.prototype.name = 'parent'