更新时间:2019年07月26日 11时17分00秒 来源:黑马程序员论坛
前言 这篇文章简单总结常用的深度比较方法,这些方法在react中用的特别多,特别是生命周期里面prop对比。因此,react和immutable天生结合性比较好。假设你项目中没有用immutable这种第三方库,那么实现深度比较的方法,在这里总结一下! 方法一[JavaScript] 纯文本查看 复制代码 function equalsObject (obj1,obj) { var p; if (obj1 === obj) { return true; } // some checks for native types first // function and sring if (typeof(obj1) === "function" || typeof(obj1) === "string" || obj1 instanceof String) { return obj1.toString() === obj.toString(); } // number if (obj1 instanceof Number || typeof(obj1) === "number") { if (obj instanceof Number || typeof(obj) === "number") { return obj1.valueOf() === obj.valueOf(); } return false; } // equalsObject(null,null) and equalsObject(undefined,undefined) do not inherit from the // Object.prototype so we can return false when they are passed as obj if (typeof(obj1) !== typeof(obj) || obj === null || typeof(obj) === "undefined") { return false; } function sort (o) { var result = {}; if (typeof o !== "object") { return o; } Object.keys(o).sort().forEach(function (key) { result[key] = sort(o[key]); }); return result; } if (typeof(obj1) === "object") { if (Array.isArray(obj1)) { // check on arrays return JSON.stringify(obj1) === JSON.stringify(obj); } else { // anyway objects for (p in obj1) { if (typeof(obj1[p]) !== typeof(obj[p])) { return false; } if ((obj1[p] === null) !== (obj[p] === null)) { return false; } switch (typeof(obj1[p])) { case 'undefined': if (typeof(obj[p]) !== 'undefined') { return false; } break; case 'object': if (obj1[p] !== null && obj[p] !== null && (obj1[p].constructor.toString() !== obj[p].constructor.toString() || !equalsObject(obj1[p],obj[p]))) { return false; } break; case 'function': if (obj1[p].toString() !== obj[p].toString()) { return false; } break; default: if (obj1[p] !== obj[p]) { return false; } } }; } } // at least check them with JSON return JSON.stringify(sort(obj1)) === JSON.stringify(sort(obj)); } var a = {a: 'text', b:[0,1]}; var b = {a: 'text', b:[0,1]}; var c = {a: 'text', b: 0}; var d = {a: 'text', b: false}; var e = {a: 'text', b:[1,0]}; var f = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }}; var g = {a: 'text', b:[1,0], f: function(){ this.f = this.b; }}; var h = {a: 'text', b:[1,0], f: function(){ this.a = this.b; }}; var i = { a: 'text', c: { b: [1, 0], f: function(){ this.a = this.b; } } }; var j = { a: 'text', c: { b: [1, 0], f: function(){ this.a = this.b; } } }; var k = {a: 'text', b: null}; var l = {a: 'text', b: undefined}; equalsObject(a,b) //true equalsObject(f,g)//true equalsObject(f,h)//false 方法二 [JavaScript] 纯文本查看 复制代码 function deepCompare(x, y) { var i, l, leftChain, rightChain; function compare2Objects(x, y) { var p; // remember that NaN === NaN returns false // and isNaN(undefined) returns true if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') { return true; } // Compare primitives and functions. // Check if both arguments link to the same object. // Especially useful on the step where we compare prototypes if (x === y) { return true; } // Works in case when functions are created in constructor. // Comparing dates is a common scenario. Another built-ins? // We can even handle functions passed across iframes if ((typeof x === 'function' && typeof y === 'function') || (x instanceof Date && y instanceof Date) || (x instanceof RegExp && y instanceof RegExp) || (x instanceof String && y instanceof String) || (x instanceof Number && y instanceof Number)) { return x.toString() === y.toString(); } // At last checking prototypes as good as we can if (!(x instanceof Object && y instanceof Object)) { return false; } if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) { return false; } if (x.constructor !== y.constructor) { return false; } if (x.prototype !== y.prototype) { return false; } // Check for infinitive linking loops if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) { return false; } // Quick checking of one object being a subset of another. // todo: cache the structure of arguments[0] for performance for (p in y) { if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { return false; } else if (typeof y[p] !== typeof x[p]) { return false; } } for (p in x) { if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { return false; } else if (typeof y[p] !== typeof x[p]) { return false; } switch (typeof(x[p])) { case 'object': case 'function': leftChain.push(x); rightChain.push(y); if (!compare2Objects(x[p], y[p])) { return false; } leftChain.pop(); rightChain.pop(); break; default: if (x[p] !== y[p]) { return false; } break; } } return true; } if (arguments.length < 1) { return true; //Die silently? Don't know how to handle such case, please help... // throw "Need two or more arguments to compare"; } for (i = 1, l = arguments.length; i < l; i++) { leftChain = []; //Todo: this can be cached rightChain = []; if (!compare2Objects(arguments[0], arguments[i])) { return false; } } return true; } 方法三 [JavaScript] 纯文本查看 复制代码 function countProps(obj) { var count = 0; for (k in obj) { if (obj.hasOwnProperty(k)) { count++; } } return count; }; function objectEquals(v1, v2) { if (typeof(v1) !== typeof(v2)) { return false; } if (typeof(v1) === "function") { return v1.toString() === v2.toString(); } if (v1 instanceof Object && v2 instanceof Object) { if (countProps(v1) !== countProps(v2)) { return false; } var r = true; for (k in v1) { r = objectEquals(v1[k], v2[k]); if (!r) { return false; } } return true; } else { return v1 === v2; } } 方法四 [JavaScript] 纯文本查看 复制代码 const hasOwnProperty = (obj1: any, obj2: any) => { switch (typeOf(obj1)) { case "object": return Object.prototype.hasOwnProperty.call(obj1, obj2); case "array": return typeOf(obj2) === "number" && obj2 >= 0 && obj1.length > obj2 ; default: return false; } }; const typeOf = (value) => Object.prototype.toString.call(value).replace(/\[|\]/gi, "").split(" ")[1].toLowerCase(); const length = (object) => { switch (typeOf(object)) { case "array": return object.length; case "object": return Object.keys(object).length; default: return 0; } }; const every = (obj, func) => typeOf(obj) === "array" ? obj.every(func) : Object.entries(obj).every(([key, value]: [any, any]) => func(value, key)); const equal = (obj1, obj2) => { switch (true) { case typeOf(obj1) === "function" && typeOf(obj2) === "function": return true; case obj1 === obj2: return true; case typeOf(obj1) === typeOf(obj2) && ["object", "array"].includes(typeOf(obj1)) && length(obj1) === length(obj2): return every(obj1, (value, key) => hasOwnProperty(obj2, key) && equal(value, obj2[key])); default: return false; } }; 本文转自:https://www.haorooms.com/post/js_deepcompare |
推荐了解热门学科
java培训 | Python人工智能 | Web前端培训 | PHP培训 |
区块链培训 | 影视制作培训 | C++培训 | 产品经理培训 |
UI设计培训 | 新媒体培训 | 产品经理培训 | Linux运维 |
大数据培训 | 智能机器人软件开发 |
传智播客是一家致力于培养高素质软件开发人才的科技公司,“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。
传智播客从未停止思考
传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”
中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。
何为中高级程序员课程?
传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展。“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。
黑马程序员热门视频教程【点击播放】
Python入门教程完整版(懂中文就能学会) | 零起点打开Java世界的大门 |
C++| 匠心之作 从0到1入门学编程 | PHP|零基础入门开发者编程核心技术 |
Web前端入门教程_Web前端html+css+JavaScript | 软件测试入门到精通 |