René's URL Explorer Experiment


Title: 从underscore源码看如何判断两个对象相等 · Issue #10 · webproblem/Blog · GitHub

Open Graph Title: 从underscore源码看如何判断两个对象相等 · Issue #10 · webproblem/Blog

X Title: 从underscore源码看如何判断两个对象相等 · Issue #10 · webproblem/Blog

Description: 首先要清楚 JavaScript 中的相等分为宽松相等(==)和严格相等(===)。宽松相等在比较值的时候会先进行类型的隐式转换,严格相等下如果比较值的类型不一致,那么就判定比较值不全等。如果比较值是引用类型,宽松相等和严格相等就不能直接判断出值是否相等了(引用类型浅拷贝比较值除外,也就是比较值指向的是同一引用地址),原因是对于任意两个不同的非原始对象,即便他们有相同的结构,都会计算得到 false 。 var num = 1; var str = '1'; conso...

Open Graph Description: 首先要清楚 JavaScript 中的相等分为宽松相等(==)和严格相等(===)。宽松相等在比较值的时候会先进行类型的隐式转换,严格相等下如果比较值的类型不一致,那么就判定比较值不全等。如果比较值是引用类型,宽松相等和严格相等就不能直接判断出值是否相等了(引用类型浅拷贝比较值除外,也就是比较值指向的是同一引用地址),原因是对于任意两个不同的非原始对象,即便他们有相同的结构,都会计算得到 f...

X Description: 首先要清楚 JavaScript 中的相等分为宽松相等(==)和严格相等(===)。宽松相等在比较值的时候会先进行类型的隐式转换,严格相等下如果比较值的类型不一致,那么就判定比较值不全等。如果比较值是引用类型,宽松相等和严格相等就不能直接判断出值是否相等了(引用类型浅拷贝比较值除外,也就是比较值指向的是同一引用地址),原因是对于任意两个不同的非原始对象,即便他们有相同的结构,都会计算得到 f...

Opengraph URL: https://github.com/webproblem/Blog/issues/10

X: @github

direct link

Domain: patch-diff.githubusercontent.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"从underscore源码看如何判断两个对象相等","articleBody":"首先要清楚 JavaScript 中的相等分为宽松相等(==)和严格相等(===)。宽松相等在比较值的时候会先进行类型的隐式转换,严格相等下如果比较值的类型不一致,那么就判定比较值不全等。如果比较值是引用类型,宽松相等和严格相等就不能直接判断出值是否相等了(引用类型浅拷贝比较值除外,也就是比较值指向的是同一引用地址),原因是对于任意两个不同的非原始对象,即便他们有相同的结构,都会计算得到 false 。\r\n\r\n```javascript\r\nvar num = 1;\r\nvar str = '1';\r\nconsole.log(num == str); // true\r\nconsole.log(num === str); // false\r\n\r\nvar obj1 = {name: '白展堂'};\r\nvar obj2 = {name: '白展堂'};\r\nvar obj3 = obj1;\r\nconsole.log(obj1 == obj2); // false\r\nconsole.log(obj1 === obj2); // false\r\nconsole.log(obj1 == obj3); // true\r\nconsole.log(obj1 === obj3); // true\r\n\r\nvar arr1 = [1];\r\nvar arr2 = [1];\r\nconsole.log(arr1 == arr2); // false\r\nconsole.log(arr1 === arr2); // false\r\n```\r\n\r\n### JSON.stringify\r\n\r\n如何判断对象是否相等?\r\n\r\n一种解决方案就是使用 JSON.stringify 序列化成字符串再做比较。\r\n\r\n```javascript\r\nvar obj1 = {name: '白展堂', age: 25};\r\nvar obj2 = {name: '白展堂', age: 25};\r\nJSON.stringify(obj1) === JSON.stringify(obj2); // true\r\n\r\nvar arr1 = ['a', 'b', 'c', 'd'];\r\nvar arr2 = ['a', 'b', 'c', 'd'];\r\nJSON.stringify(arr1) === JSON.stringify(arr2); // true\r\n```\r\n\r\n这种方案看似可以判断出对象是否相等,但是会不会存在问题呢?看过 underscore 源码的都知道,isEqual 函数的实现有多复杂,很多种情况显然不是通过 JSON.stringify 序列化就能解决的。\r\n\r\n先来分析下 JSON.stringify 方案存在的问题,假设比较对象中的属性值存在 RegExp 对象,判定结果是怎样的呢?\r\n\r\n```javascript\r\nfunction eq(a, b) {\r\n    return JSON.stringify(a) === JSON.stringify(b);\r\n}\r\nvar obj1 = {name: '白展堂', reg: /test1/i};\r\nvar obj2 = {name: '白展堂', reg: /test2/i};\r\neq(obj1, obj2); // true\r\n```\r\n\r\n结果为 true,也就是说 obj1 和 obj2 序列化的字符串是一致的。\r\n\r\n```javascript\r\nvar obj1 = {name: '白展堂', reg: /test1/i};\r\nvar obj2 = {name: '白展堂', reg: /test2/i};\r\nJSON.stringify(obj1); // \"{\"name\":\"白展堂\",\"reg\":{}}\"\r\nJSON.stringify(obj2); // \"{\"name\":\"白展堂\",\"reg\":{}}\"\r\n```\r\n\r\n可以看到,JSON.stringify 将 RegExp 对象序列化成了 '{}',也就是说 JSON.stringify 序列化对于某些情况会存在问题,比如 undefined 和 Function 函数在序列化过程中会被忽略。\r\n\r\n```javascript\r\nfunction test() {}\r\nJSON.stringify(undefined) === JSON.stringify(test); // true\r\n```\r\n\r\n### _.isEqual\r\n\r\n那么如何完美的判断对象或值相等?现在来看看 underscore 中的 isEqual 函数是如何针对不同的比较值进行处理的。\r\n\r\n#### 区分 +0 与 -0 之间的差异\r\n\r\nECMAScript 中,认为 0 与 -0 是相等的,其实不然。\r\n\r\n```javascript\r\n1 / 0 // Infinity\r\n1 / -0 // -Infinity\r\n1 / 0 === 1 / -0 // false\r\n```\r\n\r\n原因是因为 JavaScript 中的 Number 是64位双精度浮点数,采用了IEEE_754 浮点数表示法,这是一种二进制表示法,按照这个标准,最高位是符号位(0 代表正,1 代表负),剩下的用于表示大小。而对于零这个边界值 ,1000(-0) 和 0000(0)都是表示 0 ,这才有了正负零的区别。\r\n\r\n那么如何区分 0 与 -0?\r\n\r\n```javascript\r\nfunction eq(a, b) {\r\n    // 比较值a,b相等且值不是0和-0的情况\r\n    if(a === b) {\r\n        return a !== 0 || 1 / a === 1 / b; \r\n    }\r\n    return false;\r\n}\r\neq(0, 0); // true\r\neq(0, -0); // false\r\n```\r\n\r\n#### 判断值是否为 NaN\r\n\r\n判断某个值是否为 NaN 时不能直接比较这个值是否等于 NaN,因为 ECMAScript 中 NaN 不等于自身,可以使用原生函数 Number.isNaN() 或 isNaN()。\r\n\r\n```javascript\r\nvar a = NaN;\r\na === NaN; // false\r\nisNaN(a); // true\r\n```\r\n\r\n那么自己如何实现判断 NaN 值的方法?利用 NaN 不等于自身的原理。\r\n\r\n```javascript\r\nfunction eq(a, b) {\r\n    if(a !== a) return b !== b; \r\n}\r\neq(NaN, NaN); //true\r\neq(NaN, 'test'); // false\r\n```\r\n\r\n#### 隐式类型转换\r\n\r\n对于 RegExp,String,Number,Boolean 等类型的值,假设一个比较值是字面量赋值,另一个比较值的通过构造函数生成的,ECMAScript 会认为两个值并不相等。\r\n\r\n```javascript\r\nvar s1 = 'test';\r\nvar s2 = new String('test');\r\nconsole.log(s1 === s2); // false\r\ntypeof s1; // 'string'\r\ntypeof s2; // 'object'\r\n\r\nvar n1 = 100;\r\nvar n2 = new Number(100);\r\nconsole.log(n1 === n2); // false\r\ntypeof n1; // 'number'\r\ntypeof n2; // 'object'\r\n```\r\n\r\n原因是因为字面量赋值的变量和构造函数生成的变量之间的类型不同,前面说过,严格相等下不同类型的值是不全等的,那么如何处理这种情况?答案是对比较值进行隐式转换。\r\n\r\n![image](https://user-images.githubusercontent.com/20440496/48245453-ca138580-e425-11e8-81aa-a319965ce1aa.png)\r\n\r\n#### 递归遍历\r\n\r\n对于 toString() 是 Array 和 Object 类型的比较值,则循环遍历里面的元素或属性进行比较,只有length 属性值相等且里面的元素或属性都相等的情况下,就说明两个比较值是相等的了。存在一种情况就是比较值里的元素或者属性值是一个嵌套的对象,这就需要使用递归遍历。\r\n\r\n![image](https://user-images.githubusercontent.com/20440496/48246740-94719b00-e42b-11e8-9406-107e24bcb586.png)\r\n\r\nPS: underscore 源码中的 _.isEqual 源码注释地址: [源码注释](https://github.com/webproblem/Blog/blob/master/%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/underscore/Underscore.1.8.3.analysis.js#L1340-L1465)。\r\n\r\n### 参考\r\n\r\n* https://github.com/mqyqingfeng/Blog/issues/41\r\n* https://github.com/hanzichi/underscore-analysis/issues/5\r\n* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness\r\n* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify\r\n\r\n","author":{"url":"https://github.com/webproblem","@type":"Person","name":"webproblem"},"datePublished":"2018-11-09T06:33:09.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/10/Blog/issues/10"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:a89a2648-e5b2-1aa9-bcbe-a49a33cb9713
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idE2B0:83DE7:80211AA:A529851:6975DBBE
html-safe-nonceb4eab9547f55e29a58f6e3529883d8128a6669078ba2d3f24a022cf99d304b99
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFMkIwOjgzREU3OjgwMjExQUE6QTUyOTg1MTo2OTc1REJCRSIsInZpc2l0b3JfaWQiOiIxODc2ODA4MTY2NDYxMDA0NzM0IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0=
visitor-hmacb403bfb2b1681a753698bec45ddc15f997464af8558141aec53c82d728a6308f
hovercard-subject-tagissue:379040288
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/webproblem/Blog/10/issue_layout
twitter:imagehttps://opengraph.githubassets.com/0f57fe1ddf05c41514fa1b1be647df615396f630788e1076ee0450bc4f3adfa2/webproblem/Blog/issues/10
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/0f57fe1ddf05c41514fa1b1be647df615396f630788e1076ee0450bc4f3adfa2/webproblem/Blog/issues/10
og:image:alt首先要清楚 JavaScript 中的相等分为宽松相等(==)和严格相等(===)。宽松相等在比较值的时候会先进行类型的隐式转换,严格相等下如果比较值的类型不一致,那么就判定比较值不全等。如果比较值是引用类型,宽松相等和严格相等就不能直接判断出值是否相等了(引用类型浅拷贝比较值除外,也就是比较值指向的是同一引用地址),原因是对于任意两个不同的非原始对象,即便他们有相同的结构,都会计算得到 f...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamewebproblem
hostnamegithub.com
expected-hostnamegithub.com
None2bce766e7450b03e00b2fc5badd417927ce33a860e78cda3e4ecb9bbd1374cc6
turbo-cache-controlno-preview
go-importgithub.com/webproblem/Blog git https://github.com/webproblem/Blog.git
octolytics-dimension-user_id20440496
octolytics-dimension-user_loginwebproblem
octolytics-dimension-repository_id115346710
octolytics-dimension-repository_nwowebproblem/Blog
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id115346710
octolytics-dimension-repository_network_root_nwowebproblem/Blog
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
releasefcca2b8ef702b5f7f91427a6e920fa44446fe312
ui-targetcanary-1
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://patch-diff.githubusercontent.com/webproblem/Blog/issues/10#start-of-content
https://patch-diff.githubusercontent.com/
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwebproblem%2FBlog%2Fissues%2F10
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwebproblem%2FBlog%2Fissues%2F10
Sign up https://patch-diff.githubusercontent.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=webproblem%2FBlog
Reloadhttps://patch-diff.githubusercontent.com/webproblem/Blog/issues/10
Reloadhttps://patch-diff.githubusercontent.com/webproblem/Blog/issues/10
Reloadhttps://patch-diff.githubusercontent.com/webproblem/Blog/issues/10
webproblem https://patch-diff.githubusercontent.com/webproblem
Bloghttps://patch-diff.githubusercontent.com/webproblem/Blog
Notifications https://patch-diff.githubusercontent.com/login?return_to=%2Fwebproblem%2FBlog
Fork 15 https://patch-diff.githubusercontent.com/login?return_to=%2Fwebproblem%2FBlog
Star 113 https://patch-diff.githubusercontent.com/login?return_to=%2Fwebproblem%2FBlog
Code https://patch-diff.githubusercontent.com/webproblem/Blog
Issues 10 https://patch-diff.githubusercontent.com/webproblem/Blog/issues
Pull requests 0 https://patch-diff.githubusercontent.com/webproblem/Blog/pulls
Actions https://patch-diff.githubusercontent.com/webproblem/Blog/actions
Projects 0 https://patch-diff.githubusercontent.com/webproblem/Blog/projects
Security 0 https://patch-diff.githubusercontent.com/webproblem/Blog/security
Insights https://patch-diff.githubusercontent.com/webproblem/Blog/pulse
Code https://patch-diff.githubusercontent.com/webproblem/Blog
Issues https://patch-diff.githubusercontent.com/webproblem/Blog/issues
Pull requests https://patch-diff.githubusercontent.com/webproblem/Blog/pulls
Actions https://patch-diff.githubusercontent.com/webproblem/Blog/actions
Projects https://patch-diff.githubusercontent.com/webproblem/Blog/projects
Security https://patch-diff.githubusercontent.com/webproblem/Blog/security
Insights https://patch-diff.githubusercontent.com/webproblem/Blog/pulse
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/webproblem/Blog/issues/10
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/webproblem/Blog/issues/10
从underscore源码看如何判断两个对象相等https://patch-diff.githubusercontent.com/webproblem/Blog/issues/10#top
JavaScripthttps://github.com/webproblem/Blog/issues?q=state%3Aopen%20label%3A%22JavaScript%22
underscorehttps://github.com/webproblem/Blog/issues?q=state%3Aopen%20label%3A%22underscore%22
https://github.com/webproblem
https://github.com/webproblem
webproblemhttps://github.com/webproblem
on Nov 9, 2018https://github.com/webproblem/Blog/issues/10#issue-379040288
https://user-images.githubusercontent.com/20440496/48245453-ca138580-e425-11e8-81aa-a319965ce1aa.png
https://user-images.githubusercontent.com/20440496/48246740-94719b00-e42b-11e8-9406-107e24bcb586.png
源码注释https://github.com/webproblem/Blog/blob/master/%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/underscore/Underscore.1.8.3.analysis.js#L1340-L1465
JavaScript专题之如何判断两个对象相等 mqyqingfeng/Blog#41https://github.com/mqyqingfeng/Blog/issues/41
JavaScript 中是如何比较两个元素是否 "相同" 的 lessfish/underscore-analysis#5https://github.com/lessfish/underscore-analysis/issues/5
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_samenesshttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringifyhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
JavaScripthttps://github.com/webproblem/Blog/issues?q=state%3Aopen%20label%3A%22JavaScript%22
underscorehttps://github.com/webproblem/Blog/issues?q=state%3Aopen%20label%3A%22underscore%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.