我完全失去了.
我有一个功能..
Number.prototype.abs = function () {
return this >= 0 ? this : this * -1;
};
Run Code Online (Sandbox Code Playgroud)
..that返回一个数字的绝对值..
(50).abs(); // 50
(-50).abs(); // 50
Run Code Online (Sandbox Code Playgroud)
..但是没有正确比较..
(50).abs() === 50; // False
Run Code Online (Sandbox Code Playgroud)
..有时.
(50).abs() == 50; // True
(-50).abs() === 50; // True
Run Code Online (Sandbox Code Playgroud)
关于它的是,它适用于Chrome 12和Firefox 4,但不适用于IE 9,Safari 5或Opera 11.
我没有看到代码有什么问题,因为它适用于Chrome和Firefox,它是浏览器特有的,但我不知道是什么.
更新:浏览器的具体区别是严格模式支持.我在严格模式下运行我的代码,它引入了一些使我的代码工作的更改.它在浏览器中失败的原因是因为它们具有不完整或缺失的严格模式.
为什么它会返回假?
Dav*_*nco 36
即使Jeremy Heiler是正确的,他的理由也被误解了.为什么你得到object而不是number与构造函数无关.
这里的问题是this关键字.您需要了解每次使用时会发生什么this.通过ECMA草案进行一些挖掘将向您展示
this关键字的计算结果为当前执行上下文的ThisBinding的值.
(我会更改上面的内容.this关键字不会评估任何值,因为我们很快就会看到.)嗯,好的,但究竟是如何ThisBinding工作的?继续阅读!
当控件进入函数对象F中包含的函数代码的执行上下文,调用者提供thisArg和调用者提供的argumentsList时,执行以下步骤:
- 如果函数代码是严格代码,请将ThisBinding设置为thisArg.
- 否则,如果thisArg为null或未定义,则将ThisBinding设置为全局对象.
- 否则,如果Type(thisArg)不是Object,则将ThisBinding设置为 ToObject(thisArg).
- 否则将ThisBinding设置为thisArg.
- 设localEnv是调用NewDeclarativeEnvironment的结果,将F的[[Scope]]内部属性的值作为参数传递.
- 将LexicalEnvironment设置为localEnv.
- 将VariableEnvironment设置为localEnv.
- 设代码为F的[[Code]]内部属性的值.
- 使用函数代码和argumentList执行声明绑定实例化,如10.5中所述
其中就是摩擦(看看粗体部分).如果从非对象上下文调用函数,ThisBinding(也就是使用this)总是返回包装在对象内的上下文的值.解决问题的最简单方法是:
Number.prototype.abs = function () {
"use strict"; // if available
// * 1 implicitly coerces 'this' to a number value
return this >= 0 ? this * 1 : this * -1;
//... or Number(this) explicitly coerces 'this' to its toNumber value
return Number(this >= 0 ? this : this * -1);
};
Run Code Online (Sandbox Code Playgroud)
...强制this对象(或强制严格模式).但我认为了解this工作方式很重要,这个问题就是一个很好的例子.
Jer*_*emy 20
这是因为50它本身是一个Number 值,而您返回一个Number 对象.
alert(typeof 50); // number
alert(typeof (50).abs()); // object
Run Code Online (Sandbox Code Playgroud)
ECMAScript参考文献的第4.3.21节:
通过在新表达式中使用Number构造函数创建Number对象,并提供Number值作为参数.生成的对象具有内部属性,其值为Number值.通过将Number构造函数作为函数调用,可以将Number对象强制转换为Number值.
换句话说,Number 值不能严格等于Number 对象.
typeof 50 === typeof new Number(50) //--> false; number != object
Run Code Online (Sandbox Code Playgroud)
(-50).abs()正如预期的那样工作的原因是因为它正在乘以-1.当Number 对象乘以Number 值时,它将成为Number 值.在这种情况下,如果参数为正,则简单地返回对象,从而导致返回对象.
根据上面引用的参考文献,这是针对您的方法的修复:
Number.prototype.abs = function () {
return Number(this >= 0 ? this : this * -1);
};
Run Code Online (Sandbox Code Playgroud)
三等于(===)检查类型和值以确保它们相等.它失败了同样的原因,new Number(5) !== 5并new String("Text") !== "Text"在他们是不同类型的.但是,当您使用负绝对值时,您正在执行输出原始数字而不是数字对象的数学计算.因此,类型检查匹配,这是真的.
Math.abs(-50) === 50无处不在.所以你可以将Number.prototype.abs重写为:
Number.prototype.abs = function () {
return Math.abs(this);
};
Run Code Online (Sandbox Code Playgroud)
我想.Math.abs(50) === 50在IE9和Chrome 11中测试过:true
使用您的方法制作(50).abs()=== 50的其他方法可能是:
return this >= 0 ? this.valueOf() : this * -1;
return this >= 0 ? this * 1 : this * -1;
Run Code Online (Sandbox Code Playgroud)
因此,当> 0时,扩展名不会返回一个对象(this),而是一个数字值.
但我建议只使用已经可用的Math.abs方法,在这种情况下,您可以确保Math.abs(50) === 50;返回true并避免不必要的猴子补丁.
为了完整性:从选定的答案可以看出,使用strict也是一种解决方案.