如何改写JS的Array和Object原型方法使{} == []返回true?
能否通过修改原型方法让
{} == []输出true? 当然可以,这得从JavaScript中==(抽象相等)的比较规则说起:当比较对象和数组时,JS会先将两者都转换为原始值(通过ToPrimitive抽象操作),再比较转换后的结果。默认情况下,空对象{}转换为字符串是"[object Object]",空数组[]转换为字符串是"",所以"[object Object]" == ""结果为false。
我们可以通过修改原型上的方法,改变它们的原始值转换结果,从而让两者相等:
方法1:重写Object.prototype.toString
让空对象的toString返回空字符串,和空数组的默认转换结果一致:
// 保存原始方法,避免完全破坏其他功能 const originalObjToString = Object.prototype.toString; Object.prototype.toString = function() { // 判断是否为空对象(无自有可枚举属性) return Object.keys(this).length === 0 ? "" : originalObjToString.call(this); }; console.log({} == []); // 输出 true
方法2:利用Symbol.toPrimitive(ES6+)
ES6引入的Symbol.toPrimitive会优先被ToPrimitive操作调用,我们可以给Object原型添加这个方法,指定空对象的转换结果:
Object.prototype[Symbol.toPrimitive] = function(hint) { // hint表示转换的上下文(这里==会用Number hint,但返回字符串也能正常比较) return Object.keys(this).length === 0 ? "" : this.toString(); }; console.log({} == []); // 输出 true
方法3:修改valueOf方法
让空对象和空数组的valueOf返回相同的原始值(比如数字0):
// 修改Object的valueOf const originalObjValueOf = Object.prototype.valueOf; Object.prototype.valueOf = function() { return Object.keys(this).length === 0 ? 0 : originalObjValueOf.call(this); }; // 修改Array的valueOf const originalArrValueOf = Array.prototype.valueOf; Array.prototype.valueOf = function() { return this.length === 0 ? 0 : originalArrValueOf.call(this); }; console.log({} == []); // 输出 true
⚠️ 注意:这些操作都会全局修改原型方法,会影响所有Object/Array实例的行为,在实际项目中绝对不推荐这么做,只作为JS底层机制的实验性演示。
内容的提问来源于stack exchange,提问作者Dzianis Czaplia
相关产品推荐
相关产品推荐

