js extend

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-1 19:43   11   0

在使用js实现Jquery的extend函数之前,需要知道一下几个知识点

1. 基本数据类型 和 引用数据类型

基本数据类型: null, undefined,boolean, number, string, Symbol (new in ES 6)。

引用数据类型: object,

2. 堆 和 栈

栈: 系统分配指定大小的内存,系统会自动释放资源,用于存储基本数据类型

堆: 系统动态分配大小,不会被自动释放, 用于存储引用数据类型

3. 对象的浅拷贝 和 对象的深拷贝 和 对象的赋值

浅拷贝只会拷贝对象的第一层的引用,嵌套在里面的对象引用不会被复制

深拷贝是将整个对象的每个嵌套全部都拷贝下来

赋值 let a = b, 不会拷贝这个对象,a对象中的所有依旧是指向的b对象

4. 浅拷贝实现

var obj = { name: 'abc', gender: 'male', childrens: {name: 'aa', gender: 'male'} };
function extend(target, obj) {
 var result;
 if (typeof target !== 'object') {
  result = {};
 }
 else {
  result = target || {};
 }
 if (typeof obj === 'object') {
  for (let i in obj) {
   if (Object.prototype.hasOwnProperty.call(obj, i)) { // 使用Object.prototype.hasOwnProperty.call是为了避免属性名冲突
    result[i] =  obj[i]
   }
  }
 }
 return result;
}
var obj3 =  extend({}, obj);
obj3.name ="bcd";
console.log(obj); //{ name: 'abc', gender: 'male', childrens: {name: 'aa', gender: 'male'} }
console.log(obj3); //{ name: 'bcd', gender: 'male', childrens: {name: 'aa', gender: 'male'} };

5. 深拷贝实现(extend实现)

var obj = { name: 'abc', gender: [1,2,3], childrens: { name: 'aa', gender: 'male' } };
var obj2 = { key: '343', name: { name: 'bbb' } };
function isArray (arg) {
    return Object.prototype.toString.call(arg) === '[object Array]' // 判断是否是数组的方法
}

function extend () {
    var deep = false, result,args = arguments; //定义变量 deep为是否深拷贝, result为最终对象, args为源对象
    function child_extend (target, source, deep) {
        if (typeof source === 'object') {
            for (var i in source) {
                var temp = source[i];
                // 如果source[i]依旧是对象,并且需要深拷贝
                if (deep && typeof temp === 'object') {
                    // 初始化target[i],根据object和array进行不同的赋值
                    if (isArray(temp)) {
                        target[i] = [];
                    }
                    else {
                        target[i] = {}
                    }
                    child_extend(target[i], temp, deep) // 递归
                }
                else if (typeof temp !== 'undefined'){ // 如果source[i]是基本数据类型,且不是undefined
                    target[i] = temp
                }
            }
        }
    }
    
    if (args.length > 0) {
        if (typeof args[0] === 'boolean') { // 如果设置了是否深拷贝,则目标对象初始化为第二个参数, 源对象设置为第三个参数
            deep = args[0];
            result = args[1];
            args = Array.prototype.slice.call(arguments, 2);
        }
        else { // 没有设置是否深拷贝的值,则目标对象初始化为第一个参数, 源对象设置为第二个参数
            result = args[0];
            args = Array.prototype.slice.call(arguments, 1);
        }
        
        args.forEach(element => {
            // 循环遍历每一个参数
            child_extend(result,element, deep)
        });
    }
    return result;
}
var obj3 = extend(true, obj, obj2);
obj3.name.name = 'aeree';
console.log(obj3);
//{ gender: [1,2,3], childrens: { name: 'aa', gender: 'male' },key: '343', name: { name: 'bbb' } };
console.log(obj2);
// { key: '343', name: { name: 'bbb' } }

可以看到设置了深拷贝之后,目标对象的修改 不会 影响到源对象

转载于:https://my.oschina.net/u/4085373/blog/3022063

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP