原型遗传:为什么假不等于假
Prototypal Inheritance: Why is false not equal to false?
我快速起草了一个小辅助方法,使未定义的变量检查更容易一些。
Object.prototype.is = function() {
for(var i in arguments) {
if(this === arguments[i]) {
return true;
}
}
return false;
};
设计如下:foo.is(undefined, false)
检查foo是未定义的还是假的。我使用的测试用例是:
var a = false;
a.is(false);
> false
有点困惑,我又玩了一下。一些控制台日志记录显示相等性检查失败,因为要比较的两个对象不同。
Boolean {is: function} === false
> false
因此,a
从它的曾祖父那里继承了is
方法:Object.prototype,但比较中的false
没有。
我想我可以通过使用new Boolean(false)
强制继承,这肯定会创建一个对象的新实例(希望可以规避引用在扩展 Object 原型之前创建的对象时可能发生的任何风险)。结果:
Boolean {is: function} === Boolean {is: function}
> false
为什么相等性检查失败?
作为解决这里发生的事情的过程的一部分,我在用单个布尔值作为参数调用函数后检查了参数数组,结果发现它的长度为二,额外的参数是在 Object.prototype 中声明的is
函数。
a.is(false);
arguments -> [false, is: function]
结果如何?
作为参考,我知道像这样的猴子补丁是一个坏主意!这不是生产代码,我只是感兴趣。
> 有什么问题?
这是将this
值强制到对象的另一个问题 - 猴子补丁是将'use strict'
添加到函数的开头,从而防止这种强制发生。但是,较旧的浏览器可能无法识别此指令。
如果函数不严格,则基本上会发生以下情况:
var a = false;
Object.prototype.is.call(Object(a), undefined, false);
当a
转换为对象(通过调用Object(a)
)时,它被转换为布尔对象,这与布尔值不同。例如,以这个为例:
false === new Boolean(false); // false
此外,对象仅在引用同一对象时才相等:
new Boolean(false) === new Boolean(false); // false
var test = new Boolean(false);
test === test; // true, they are the same object
出现的另一个问题是,当使用 null
调用is()
函数时(它并不严格),它将失败:
Object.prototype.is.call(null, null); // becomes window === null (false)
我能做些什么呢?
使其成为严格函数的替代方法包括比较两者的对象值(尽管这使得像new Boolean(false).is(false)
和new Boolean(false).is(new Boolean(false))
这样的东西变成真的,这可能是无意的。
你可以采取的另一种选择是使其成为非原型函数,即使其成为类似于Object.is
函数(尽管请注意 ES6 可能会定义一个原生Object.is
函数,该函数的行为与您的函数不同):
Object.oneIsEqual = function (arg, compare)
{ for(var i = 0; i < compare.length; ++i) if (arg === compare[i]) return true;
return false;
};
关于编辑的注意事项:
之所以在for-in
循环中获取原始函数,是因为您已经在原型上定义了它,并且它是可枚举的(稍后会详细介绍)。
arguments
对象有一个Object.prototype
的原型,它允许is
函数可以在arguments
上访问。
Object.prototype.is = function() {
for(var i in arguments) {
if(this === arguments[i]) {
return true;
}
}
return false;
};
(function () { return arguments.is; })(); // is the same function as to Object.prototype.is
默认情况下(当您"正常"定义它时),所有属性(无论是直接在对象上还是在原型链上)都是可枚举的,这意味着您可以在for-in
循环和其他类似构造中看到它。但是,这(大多数时候)不是所需的行为 - 大多数本机原型函数不可枚举。若要解决此问题,应运行函数的索引,而不是属性:
for (var i = 0; i < arguments.length; ++i) // code here
- 可以'我不明白为什么;t将行和单元格添加到表中
- Don'我不明白为什么我的setInterval+jQuery;不起作用
- 这个旋钮没有更新;我不知道为什么
- 我不知道为什么我的代码是错误的?又有什么错
- CORS:访问控制允许原点不等于提供的原点
- I'我不知道为什么我的代码没有'不起作用
- sqlite查询返回错误-can'我不知道为什么
- JQuery `length`属性工作不正常.为什么?
- 我可以'我不明白为什么我能;不要在JavaScript中更改蜡笔的颜色
- 我没有'我不知道为什么我的jqGrid子网格没有'不要给我看数据
- 为什么我的 React getDOMNode().textContent JavaScript 字符串不等于字符串
- 原型遗传:为什么假不等于假
- 为什么 +true 不等于 true.valueOf
- 为什么“this”不等于“Object”,为什么属性是“undefined”
- 为什么"1.0〃;不等于“+1.0〃;在JavaScript中
- 为什么"i〃;不等于“;i̇”;
- 为什么undefined在JavaScript中不等于零
- 为什么IE's插入符在文本输入中的位置不等于字符串索引?解决方法是什么?
- 为什么我掷1时分数不等于0
- 为什么readyState不等于4