Preface
The $.extend() in jQuery is a frequently used tool function, mostly used to merge parameters (objects). The specific usage will not be described here. You can control whether or not the merging process is done by passing parameters. Use deep copy; the new Object.assign() method in ES2015 can also realize object merging, but a shallow copy is used during the merging process; this article refers to the source code of jQuery's extend method to implement object merging by itself. That is, copying the attributes of multiple objects to the target object. If there are the same attributes, the later objects will overwrite the previous ones.
A previous blog post specifically introduced the deep and shallow copies of objects and arrays. If you don’t understand, please read here. Let’s look at the implementation first and then explain
function extend() { //extend 浅拷贝实现 var name,options,copy, length = arguments.length, i = 1, target = arguments[0] || {}; //取目标对象 if(['object','function'].indexOf(typeof target) < 0){ target = {}; } for(;i<length;i++){ options = arguments[i] if(options != null){ //排除空参数的情况 extend({},,) for(name in options){ //遍历对象 赋值 copy = options[name]; if (copy !== undefined) { target[name] = copy; } } } } return target } //测试数据 var test1 = { a : 1, b : { c : 2, d : 3 }, e : [1,'a'] }, test2 = { b : { c : 4, d : 5, f : 6 }, e : [1,'a'], g : 7 } var test = extend({},test1,test2); console.log(test.b.d); //5 test2.b.d = 'x'; //修改test2 console.log(test.b.d); // 'x' test随之修改
The ideas are as follows:
1. By default, the first parameter is taken as the target object. If the first parameter is not object data Type, then assign the value to an empty object
2. Traverse the remaining parameters (source object) and copy the properties of the source object to the target object.
3. Return the target object as the merged result
In the second step, the attribute values of the source object are not judged. All are assigned using '=', so when the source object's attribute value When the attribute value is an object attribute, only the reference value is copied, which is a shallow copy. From the test results, it can be seen that the attribute values of the b attribute of test and test2 use the same object and will affect each other. After knowing this, you should have an idea on how to implement deep copy during merge.
When copying the source object attribute value, you need to determine the type of the value. If it is an object data type, call the extend function recursively. Then you can practice object merging in deep copy mode, and the implementation is as follows:
function extend() { //extend 深拷贝实现 var name,options,src,copy, deep = false, //是否深拷贝 默认为false length = arguments.length, i = 1, target = arguments[0] || {}; //如果第一个参数为boolean类型,赋值给deep if(typeof target == 'boolean'){ deep = arguments[0]; target = arguments[i] || {}; //目标对象顺延 i++; } //如果target不是对象数据类型的话 target赋值为 {} if(['object','function'].indexOf(typeof target) < 0){ target = {}; } for(;i<length;i++){ options = arguments[i]; if(options != null){ for(name in options){ copy = options[name]; src = target[name]; if(target === copy){ //避免重复循环 continue; } if(deep && copy && (typeof copy == 'object')){ // 类型判断 src = Object.prototype.toString.call(copy) == '[object Array]' ? [] : {}; //区分数组和‘对象’ target[name] = extend(deep,src,copy); }else { if (copy !== undefined) { target[name] = copy; } } } } } return target }
1. Parameter judgment, if the first parameter is a Boolean type, it is taken to control whether to deep copy The parameter deep, deep defaults to false; at the same time, the target element will be the second parameter
2. When copying the attribute value, you must determine the type of the deep parameter and attribute value; if deep is true and the attribute value is an object Type, call the extend function recursively, otherwise assign the value directly
3. It is necessary to distinguish between arrays and 'objects' to assign different initial values to the properties of the target object. If they are all {}, the attribute value of the array type copied to the target element will become {'0':xx, '1': xx...}
Always They are all using $.extend() directly. It is easy to use but I am not very clear about the implementation. I* may not be rigorous in the implementation, but I feel that the harvest is good.
The above is the detailed content of How to implement object merging function. For more information, please follow other related articles on the PHP Chinese website!