Underscore.js 是一个流行的 JavaScript 库,提供了许多实用的函数来操作数组、集合、对象等数据类型。其中,contains 函数可以用于判断一个值是否存在于一个数组或字符串中。但是,在对象类型上使用 contains 函数有一些需要注意的地方。
对象类型的 contains 函数
在 Underscore.js 中,contains 函数支持以下两种调用方式:
- _.contains(array, value):判断 value 是否存在于 array 数组中;
- _.contains(object, value):判断 value 是否为 object 对象的一个属性值。
下面我们重点介绍第二种调用方式的使用方法。
例如,我们有一个对象数组,每个对象都有一个 name 属性:
var users = [ { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 35 } ];
我们可以使用 contains 函数来判断某个名字是否存在于该数组中:
_.contains(users, { name: 'Bob' }); // 返回 false
这里返回了 false,因为 contains 函数使用的是 JavaScript 的“引用比较”,即只有当两个对象引用同一个内存地址时才会返回 true。而在上面的代码中,{ name: 'Bob' } 是一个新的对象,和数组中的 { name: 'Bob', age: 30 } 不是同一个对象,因此返回了 false。
那么该如何正确地使用 contains 函数呢?我们需要使用 Underscore.js 提供的 find 函数来查找数组中满足条件的对象。例如,要判断名字为 Bob 的用户是否存在,可以这样写:
_.find(users, { name: 'Bob' }) !== undefined; // 返回 true
这里先使用了 find 函数查找到第一个名字为 Bob 的用户对象,如果返回的结果不是 undefined,则说明该对象存在于数组中。
深度比较
上述例子中的问题是由于 JavaScript 对象的引用比较导致的。但是,如果我们想要在对象类型上进行“值比较”呢?例如,以下对象数组中两个对象的属性值相同:
-- -------------------- ---- ------- --- ----- - - - --- -- ------ -------- ------ --- -- - --- -- ------ --------- ------ --- -- - --- -- ------ ------- ------ --- -- - --- -- ------ ------- ------ --- -- - --- -- ------ --------- ------ --- -- - --- -- ------ ------------ ------ --- - -- --- ------- - - --- -- ------ -------- ------ --- --
此时,我们希望通过 contains 函数来判断 newItem 是否在 items 中。但是,由于 newItem 和 items 中的对象并不是同一个对象,因此简单的调用 contains 函数会得到错误的结果:
_.contains(items, newItem); // 返回 false
为了实现“值比较”,我们需要使用 Underscore.js 提供的 isEqual 函数来比较对象。可以自定义一个新的包装函数:
_.mixin({ containsValue: function(collection, value){ return _.some(collection, function(item){ return _.isEqual(item, value); }); } });
这里的 containsValue 函数使用 some 函数遍历集合中的每个元素,并使用 isEqual 函数比较集合中的元素和目标元素是否相等。如果找到了相等的元素,则返回 true;否则返回 false。
通过调用新的 containsValue 函数,我们可以得到正确的结果:
_.containsValue(items, newItem); // 返回 true
结论
在对象类型上使用 contains 函数需要注意以下几点:
- 对象类型的 contains 函数是通过“引用比较”来判断对象
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/27667