/**
* 对象属性拷贝
*
* @param {Object} target 目标对象
* @param {Object} source 源对象
* @return {Object} 返回目标对象
*/
function extend(target, source) {
for (var key in source) { // 1
if (source.hasOwnProperty(key)) { // 2
var value = source[key];
if (typeof value !== 'undefined') {
target[key] = value; // 3
}
}
}
return target;
}
extend 函数用于拷贝对象属性。通过 for in 循环 source 对象中的可遍历属性, 需要注意的是 for in 循环也能遍历到对象上的继承属性,所以使用 hasOwnProperty 函数判断是否是属于自身属性,如果属于自身属性的拷贝,就进行拷贝(这里需要注意的是拷贝不是深拷贝而是浅拷贝)。最后返回目标对象
1. for in 循环
for in 循环大部分用于遍历对象,不用于遍历数组。
mdn 描述
for…in 语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性。
使用for in时需要注意一下几点

2. hasOwnProperty() 函数
解释:该方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性,它不会在对象原型链中检查指定的属性。
3. target[key] = value
target[key] = value
这条赋值语句并没有判断tagrget中是否已经已经存在key,而是直接赋值,并且属于浅拷贝。
1.extend 函数拷贝对象
let khTarget = {};
let khSource = {
apple: {
watch: ['s7', 's8', 's9'],
}
};
console.log(extend(khTarget, khSource));

其实当执行完 extend 函数属性拷贝后,直接打印 khTarget 变量结果和打印 extend(khTarget, khSource) 结果一致
let khTarget = {};
let khSource = {
apple: {
watch: ['s7', 's8', 's9'],
}
};
extend(khTarget, khSource)
console.log(khTarget); // 用到了副作用

2.extend 函数是浅拷贝
let khTarget = {};
let khSource = {
apple: {
watch: ['s7', 's8', 's9'],
}
};
extend(khTarget, khSource)
khSource.apple.watch.push('s10'); // 修改原来对象中的数据
console.log(khTarget); // 目标对象也跟着修改

参考文档