浅拷贝的使用场景
- Object.assign
- … 扩展运算符
- Array.prototype.slice.call
浅拷贝的实现
其原理就是 拷贝一个对象的属性到另一个对象中
var shallowCopy = function (obj) {
if (typeof obj !== 'Object') return
// 根据obj的类型创建新的newObj
var newObj = obj instanceof Array ? [] : {}
// 遍历obj的属性
for (var key in newObj) {
if (obj.hasOwnProperty(key) {
newObj[key] = obj[key]
})
}
return newObj
}
深拷贝的实现
拷贝的时候判断一下属性值的类型,如果是对象,递归调用深拷贝函数即可
var deepCopy = function (obj) {
if (typeof obj !== 'Object') return
var newObj = obj instanceof Array ? [] : {}
for (var key in newObj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
}
}
}
学习jquery中的extend
第一步,我们根据上面浅显的浅拷贝实现来写一下extend方法
function extend () {
var copy, options, name
var length = arguments.length
var target = arguments[0]
for (var i = 1; i < length; i++) {
options = arguments[i]
if (options !== null) {
for (name in options) {
copy = options[name]
if (copy !== undefined) {
target[name] = copy
}
}
}
}
return target
}
var obj1 = {
a: 1,
b: { b1: 1, b2: 2 }
};
var obj2 = {
b: { b1: 3, b3: 4 },
c: 3
};
var obj3 = {
d: 4
}
console.log(extend(obj1, obj2, obj3))
进行深拷贝
function deepExtend () {
var copy, options, name, src
// 默认值为false
var deep = false
var length = arguments.length
// 记录要复制的对象的下标
var i = 1
var target = arguments[0] || {}
// 如果第一个参数是个布尔值
if (typeof target === 'boolean') {
deep = target
target = arguments[i] || {}
i++
}
// 只有对象才可以进行复制,所以要判断一下
if (typeof target !== 'Object') {
target = {}
}
for (; i < length; i++) {
options = arguments[i]
for (name in options) {
src = target[name]
copy = options[name]
// 如果对象里面还是对象,并且要求深拷贝的话
if (deep && copy && typeof copy === 'object') {
target[name] = deepExtend(deep, src, copy)
} else {
target[name] = copy
}
}
}
return target
}
// 测试例子
var obj1 = {
a: 1,
b: { b1: 1, b2: 2 }
};
var obj2 = {
b: { b1: 3, b3: 4 },
c: 3
};
var obj3 = {
d: 4
}
console.log(deepExtend(true, obj1, obj2, obj3));
这样就实现了,当对象中存在的对象时,也能正确的遍历
对以上进行一下优化
其实就是把重复的方法提取出来,比如判断某元素是否是对象
let isObject = (source) => {
return Object.prototype.toString.call(source) === '[object Object]'
}
let deepExtend = () => {
let copy, name, options, target, src
let deep = false
let i = 1
let length = arguments.length
target = arguments[0] || {}
if (typeof target === 'boolean') {
deep = target
target = arguments[i] || {}
i++
}
if (!isObject(target)) {
target = {}
}
for (; i < length; i++) {
options = arguments[i]
if (options !== null) {
for (name in options) {
src = target[name]
copy = options[name]
if (deep && copy && isObject(copy)) {
target[name] = deepExtend(deep, src, copy)
} else {
target[name] = copy
}
}
}
}
return target
}