看 MDN Beginners 文档的时候注意到了这种用法 var n1 = Number(123); , 冒出的第一个疑问就是和 var n2 = new Number(123); 有什么区别呢?
首先用 typeof 做下探测, n1 是 number 而 n2 是 object, 他们的本质区别就是 type 不同.
那么有趣的问题来了, Number 内部肯定知道是怎么调用的它, 那是怎么实现的呢
最先想到的就是根据 caller 来区分, 但在实验的过程中发现两个问题:
全局调用的时候没有 caller
就算知道 caller 也无法区分它是 function 调用还是构造对象
既然需要在运行期区分, 那么该 "真爱" this 登场了
万事俱备撸起袖子开干, But... 先等等, 在开工前先用测试数据探测下 Number 的行为:
console.log(Number(123)); //123
console.log(Number( + 123)); //123
console.log(Number( - 123)); //-123
console.log(Number("123")); //123
console.log(Number("+123")); //123
console.log(Number("-123")); //-123
console.log(Number("abc123")); //NaN
console.log(Number(NaN)); //NaN
console.log(new Number(123)); //save as above except type
console.log(new Number( + 123));
console.log(new Number( - 123));
console.log(new Number("123"));
console.log(new Number("+123"));
console.log(new Number("-123"));
console.log(new Number("abc123"));
console.log(new Number(NaN));
我们的简单实现命名为 WNumber, 测试过程发现 123 == new Number('123') 是返回 true 的, 但我们的 WNumber 却返回 false, 难道浏览器不给 WNumber 国民待遇
首先浏览器是不可能把 123 auto-box 成 Number 对象的, 因为两个对象 == 是 false 的, 所以肯定是把 Number 对象 auto-unbox 成原始 type(值 type). 查了一下对象刚好有个 valueOf() 方法用来返回这个对象代表的原始值. (后来测试过程中发现 valueOf() 或 toString() 实现任一一个方法都能让浏览器返回 true)
下面是 WNumber 的源码
function WNumber(i) {
var primitiveValue = 0;
if (typeof i === "number") {
primitiveValue = i;
} else {
var regR = /^([\+\-]?)([1-9][0-9]*)$/.exec(i);
if (regR !== null) {
var nstrlen = regR[2].length;
var nResult = arguments.callee(0);
for (idx in regR[2]) {
nResult += regR[2][idx] * Math.pow(10, nstrlen - idx - 1);
}
if (regR[1] === '-') {
primitiveValue = -nResult;
} else {
primitiveValue = nResult;
}
} else {
primitiveValue = NaN;
}
}
if (this instanceof WNumber) {
//construct object
this.valueOf = function() {
return primitiveValue;
}
this.toString = function() {
return primitiveValue + '';
}
return this;
} else {
//invoke as function
return primitiveValue;
}
}
来源: https://www.cnblogs.com/DebuggerWei/p/8330866.html