Javascript 字符串“null”(非null未定义的未转换为字符串“null”。。。你能花一点时间来理解JSON.stringify是如何工作的吗?哎呀,好像回到了我匆忙中欺骗自己误读别人的评论的那一天,所以说了一个无关紧要的谎言(即JSON.stringify(nul
Javascript 字符串“null”(非null未定义的未转换为字符串“null”。。。你能花一点时间来理解JSON.stringify是如何工作的吗?哎呀,好像回到了我匆忙中欺骗自己误读别人的评论的那一天,所以说了一个无关紧要的谎言(即JSON.stringify(nul,javascript,Javascript,字符串“null”(非null未定义的未转换为字符串“null”。。。你能花一点时间来理解JSON.stringify是如何工作的吗?哎呀,好像回到了我匆忙中欺骗自己误读别人的评论的那一天,所以说了一个无关紧要的谎言(即JSON.stringify(null)=“null”)。关于OP的问题,我仍然没有看到我在回答中没有提到的任何未定义或空值的问题。因此,我支持我的答案,它的demo tests.JSON.stringify不能保证它将对象转换为相同的字符串。每次都是。一个有趣的答案!这是有用的
字符串“null”(非
null
未定义的未转换为字符串“null”
。。。你能花一点时间来理解JSON.stringify是如何工作的吗?哎呀,好像回到了我匆忙中欺骗自己误读别人的评论的那一天,所以说了一个无关紧要的谎言(即JSON.stringify(null)=“null”)。关于OP的问题,我仍然没有看到我在回答中没有提到的任何未定义或空值的问题。因此,我支持我的答案,它的demo tests.JSON.stringify不能保证它将对象转换为相同的字符串。每次都是。一个有趣的答案!这是有用的关于[3,2,1].toString()=[1,2,3].toString()
@Reza这不起作用,除非sorted@KevinDanikowski是的,这正是我的观点,我的意思是这个答案不适用于我所指的情况。如果数组包含的不是简单值,请小心Array.prototype.sort()
很浅,Array.prototype.toString()
将对象转换为[object object]
,并展平任何嵌入的数组,这可能会导致误判。我不明白为什么这会被否决:到目前为止,这是唯一一个真正得到(未指定)结果的解决方案示例正确…a.sort()
不仅返回已排序的版本。它会改变阵列本身,这可能会以意想不到的方式影响应用程序。@feihcsim你错了。[12,34,56]。toString()//结果:“12,34,56”而[1,23,456]。toString()//结果:“1,23456”因此,它们并不相等您是对的-但是问题仍然存在:['1,2',3]。toString()===[1,'2,3']。toString()
是误报,如果数组包含对象会发生什么,哪个属性指向同一个对象?TypeError:将循环结构转换为JSON
感谢@jusio指出这一点,我在回答中已经明确了。您的代码是如何处理指向自己的对象的?@jusio Hi,很抱歉延迟,没有太多空闲时间。这个特殊的例子不涉及自引用,但看看它的功能。经过更多的测试和反馈后,我将编辑答案中的一个uKolka@jusio这是。我已经为新的测试用例更新了它。当vara={},b={}时失败;a、 self=a;b、 self={}代码>和在其他一些情况下。请不要编辑您不需要的对象的原型own@Umur康塔克有罪。我会在某个时候更新它。(这本来不是我的代码,但编写它的人不想发布它)为什么要对代码进行排序?如果数组包含对象,这不起作用。@GijsjanB如果数组包含相同的对象,它会起作用。当然,如果对象不完全相同,并且您希望比较对象本身,那么它就不起作用。但这不是问题所在。你能在回答中解释为什么我们不应该使用stringify
或
?这个例子似乎表明不应该考虑数字的顺序([1,2,3]=[3,2,1])。但是,不解决此问题的答案被标记为正确答案,并且唯一实际解决此问题的答案(使用sort())是donwvote。。。。如果排序不相关,则应在示例中修复。否则,被标记为正确的答案就不可能是正确的。对两个Number
s进行简单比较的最简单方法不是这样做吗?a、 each((v,i)=>v==b[i])b.each((v,i)=>v==c[i])在ES6中,只需执行a.each(item=>b.includes(item))&b.each(item=>a.includes(item))
。不要忘了检查两边,因为如果你每次只做一个,你可以处理这种情况:a=[3,3,3],b=[1,2,3]
,而它是false。下划线是我每天使用的库。由于它的简单性,它应该被评得更高。下划线已经被更高级的库所取代。因为它是下划线的超集,所以它还支持u.isEqual(a,b)。查看更多详细信息。我喜欢lodash,它确实包含一组超级下划线功能。。。但它既不“优越”,也没有“取代”下划线。首先,Lodash已经过元编程和微优化,其源代码基本上无法读取。当(比如)您意外地将错误的参数传递给Lodash/下划线函数,并且必须调试正在发生的事情时,这一点很重要。在这种情况下,下划线是非常优越的,因为(与Lodash不同)您实际上可以读取源代码。归根结底,两个图书馆都不比另一个好,它们只是有着不同的优势和劣势。作为补充说明,这两个图书馆的作者(约翰·大卫·道尔顿和杰里米·阿什凯纳斯)最近讨论了合并它们的前景,因为它们的共同点。但是(如果阅读GitHub线程,您会发现:)这不是一个明显的决定。事实上,AFAIK在此后的3个多月内没有做出任何决定,这正是因为下划线具有可读的源代码等优点,下划线用户不想丢失。回到手头的主题,这会提醒false | false
<代码>.\uEqual(a,b)
根据数组元素的顺序对其进行比较,因此如果需要不区分顺序的比较,则必须在比较之前对数组进行排序。通常建议不要修改/扩展现有的全局对象。最好使用===而不是==对吗?@ChetPrickles取决于您想要什么,像往常一样:-)是否希望undefined
等于null
,0等等?如果您有两个类似的数组:[3,3,3]和[1,2,3]
,则它不起作用,因为您的代码将返回true而不是。因此,您必须在两侧执行每个。好的。我之所以选择这个主题,是因为我在搜索相同的东西,但没有索引相等。但好吧,你是对的。这与所问问题的答案不相关。我不能
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
alert(a == b + "|" + b == c);
function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }
> arrays_equal([1,2,3], [1,3,4])
false
> arrays_equal([1,2,3], [1,2,3])
true
> arrays_equal([1,3,4], [1,2,3])
false
> arrays_equal(null, [1,2,3])
false
> arrays_equal(null, null)
false
function arraysEqual(a1,a2) {
/* WARNING: arrays must not contain {objects} or behavior may be undefined */
return JSON.stringify(a1)==JSON.stringify(a2);
}
[1, 2, 3].toString() == [1, 2, 3].toString()
true
[1, 2, 3,].toString() == [1, 2, 3].toString()
true
[1,2,3].toString() == [1, 2, 3].toString()
true
[[1,2],[3]].toString() == [[1],[2,3]].toString()
true
Array.prototype.equals = function(array) {
return array instanceof Array && JSON.stringify(this) === JSON.stringify(array) ;
}
a = [1, [2, 3]]
a.equals([[1, 2], 3]) // false
a.equals([1, [2, 3]]) // true
function deepEquals(obj1, obj2, parents1, parents2) {
"use strict";
var i;
// compare null and undefined
if (obj1 === undefined || obj2 === undefined ||
obj1 === null || obj2 === null) {
return obj1 === obj2;
}
// compare primitives
if (typeof (obj1) !== 'object' || typeof (obj2) !== 'object') {
return obj1.valueOf() === obj2.valueOf();
}
// if objects are of different types or lengths they can't be equal
if (obj1.constructor !== obj2.constructor || (obj1.length !== undefined && obj1.length !== obj2.length)) {
return false;
}
// iterate the objects
for (i in obj1) {
// build the parents list for object on the left (obj1)
if (parents1 === undefined) parents1 = [];
if (obj1.constructor === Object) parents1.push(obj1);
// build the parents list for object on the right (obj2)
if (parents2 === undefined) parents2 = [];
if (obj2.constructor === Object) parents2.push(obj2);
// walk through object properties
if (obj1.propertyIsEnumerable(i)) {
if (obj2.propertyIsEnumerable(i)) {
// if object at i was met while going down here
// it's a self reference
if ((obj1[i].constructor === Object && parents1.indexOf(obj1[i]) >= 0) || (obj2[i].constructor === Object && parents2.indexOf(obj2[i]) >= 0)) {
if (obj1[i] !== obj2[i]) {
return false;
}
continue;
}
// it's not a self reference so we are here
if (!deepEquals(obj1[i], obj2[i], parents1, parents2)) {
return false;
}
} else {
// obj2[i] does not exist
return false;
}
}
}
return true;
};
// message is displayed on failure
// clean console === all tests passed
function assertTrue(cond, msg) {
if (!cond) {
console.log(msg);
}
}
var a = 'sdf',
b = 'sdf';
assertTrue(deepEquals(b, a), 'Strings are equal.');
b = 'dfs';
assertTrue(!deepEquals(b, a), 'Strings are not equal.');
a = 9;
b = 9;
assertTrue(deepEquals(b, a), 'Numbers are equal.');
b = 3;
assertTrue(!deepEquals(b, a), 'Numbers are not equal.');
a = false;
b = false;
assertTrue(deepEquals(b, a), 'Booleans are equal.');
b = true;
assertTrue(!deepEquals(b, a), 'Booleans are not equal.');
a = null;
assertTrue(!deepEquals(b, a), 'Boolean is not equal to null.');
a = function () {
return true;
};
assertTrue(deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
]), 'Arrays are equal.');
assertTrue(!deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': '1'
},
true]
]), 'Arrays are not equal.');
a = {
prop: 'val'
};
a.self = a;
b = {
prop: 'val'
};
b.self = a;
assertTrue(deepEquals(b, a), 'Immediate self referencing objects are equal.');
a.prop = 'shmal';
assertTrue(!deepEquals(b, a), 'Immediate self referencing objects are not equal.');
a = {
prop: 'val',
inside: {}
};
a.inside.self = a;
b = {
prop: 'val',
inside: {}
};
b.inside.self = a;
assertTrue(deepEquals(b, a), 'Deep self referencing objects are equal.');
b.inside.self = b;
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equeal. Not the same instance.');
b.inside.self = {foo: 'bar'};
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equal. Completely different object.');
a = {};
b = {};
a.self = a;
b.self = {};
assertTrue(!deepEquals(b, a), 'Empty object and self reference of an empty object.');
a = [1,2,3]
b = [3,2,1]
a.sort().toString() == b.sort().toString()
var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);
alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));
_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false
_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
// Please note that calling sort on an array will modify that array.
// you might want to clone your array first.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
Array.prototype.equals = function( array ) {
return this.length == array.length &&
this.every( function(this_i,i) { return this_i == array[i] } )
}
_.mixin({
/**
Tests for the equality of two variables
valA: first variable
valB: second variable
stringifyStatics: cast non-objects to string so that "1"===1
**/
equal:function(valA,valB,stringifyStatics){
stringifyStatics=!!stringifyStatics;
//check for same type
if(typeof(valA)!==typeof(valB)){
if((_.isObject(valA) || _.isObject(valB))){
return false;
}
}
//test non-objects for equality
if(!_.isObject(valA)){
if(stringifyStatics){
var valAs=''+valA;
var valBs=''+valB;
ret=(''+valA)===(''+valB);
}else{
ret=valA===valB;
}
return ret;
}
//test for length
if(_.size(valA)!=_.size(valB)){
return false;
}
//test for arrays first
var isArr=_.isArray(valA);
//test whether both are array or both object
if(isArr!==_.isArray(valB)){
return false;
}
var ret=true;
if(isArr){
//do test for arrays
_.each(valA,function(val,idx,lst){
if(!ret){return;}
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}else{
//do test for objects
_.each(valA,function(val,idx,lst){
if(!ret){return;}
//test for object member exists
if(!_.has(valB,idx)){
ret=false;
return;
}
// test for member equality
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}
return ret;
}
});
_.equal([1,2,3],[1,2,"3"],true)
_.equal(
['a',{b:'b',c:[{'someId':1},2]},[1,2,3]],
['a',{b:'b',c:[{'someId':"1"},2]},["1",'2',3]]
,true);
var deepCompare = (function() {
function internalDeepCompare (obj1, obj2, objects) {
var i, objPair;
if (obj1 === obj2) {
return true;
}
i = objects.length;
while (i--) {
objPair = objects[i];
if ( (objPair.obj1 === obj1 && objPair.obj2 === obj2) ||
(objPair.obj1 === obj2 && objPair.obj2 === obj1) ) {
return true;
}
}
objects.push({obj1: obj1, obj2: obj2});
if (obj1 instanceof Array) {
if (!(obj2 instanceof Array)) {
return false;
}
i = obj1.length;
if (i !== obj2.length) {
return false;
}
while (i--) {
if (!internalDeepCompare(obj1[i], obj2[i], objects)) {
return false;
}
}
}
else {
switch (typeof obj1) {
case "object":
// deal with null
if (!(obj2 && obj1.constructor === obj2.constructor)) {
return false;
}
if (obj1 instanceof RegExp) {
if (!(obj2 instanceof RegExp && obj1.source === obj2.source)) {
return false;
}
}
else if (obj1 instanceof Date) {
if (!(obj2 instanceof Date && obj1.getTime() === obj2.getTime())) {
return false;
}
}
else {
for (i in obj1) {
if (obj1.hasOwnProperty(i)) {
if (!(obj2.hasOwnProperty(i) && internalDeepCompare(obj1[i], obj2[i], objects))) {
return false;
}
}
}
}
break;
case "function":
if (!(typeof obj2 === "function" && obj1+"" === obj2+"")) {
return false;
}
break;
default: //deal with NaN
if (obj1 !== obj2 && obj1 === obj1 && obj2 === obj2) {
return false;
}
}
}
return true;
}
return function (obj1, obj2) {
return internalDeepCompare(obj1, obj2, []);
};
}());
/*
var a = [a, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null],
b = [b, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null];
deepCompare(a, b);
*/
var a= [1, 2, 3, '3'];
var b = [1, 2, 3];
var c = a.filter(function (i) { return ! ~b.indexOf(i); });
alert(c.length);
function arraysEqual (a1, a2) {
return a1 === a2 || (
a1 !== null && a2 !== null &&
a1.length === a2.length &&
a1
.map(function (val, idx) { return val === a2[idx]; })
.reduce(function (prev, cur) { return prev && cur; }, true)
);
}
// arr1 & arr2: Arrays of objects
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be 'id'
function areEqual (arr1, arr2, sortProperty) {
return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
_.xor(a, b).length === 0
true
_.xor(b, c).length === 0
true
function equalArray(a, b) {
if (a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
} else {
return false;
}
}