码迷,mamicode.com
首页 > 其他好文 > 详细

Number()和new Number()的区别以及造个简单的轮子

时间:2018-02-03 23:04:50      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:简单   false   tostring   height   code   except   body   obj   value   

  看JavaScript文档的时候注意到了这种用法 var n1 = Number(123); , 冒出的第一个疑问就是和 var n2 = new Number(123); 有什么区别呢? 

 

  首先用typeof做下探测, n1是number而n2是object, 他们的本质区别就是type不同.

 

  那么有趣的问题来了, Number内部肯定知道是怎么调用的它. 假设在没有Number的情况下, 如果我们要实现个类似的类应该怎么做呢?

 

  最先想到的就是根据caller来区分, 但在实验的过程中发现两个问题:

  1. 全局调用的时候没有caller
  2. 就算知道caller也无法区分它是function调用还是构造对象

 

  所以caller这条路就走不通了, 既然需要在运行期区分, 那么该"真爱" this 登场了. this指向当前构造的对象, 我们就可以区分是function调用还是构造对象了.

 

  我们的新轮子命名为WNumber, 思路理清楚后就剩施工了. 为了更接近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的, 但我们的 123 == new WNumber(‘123‘) 却返回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 = /^([\+\-]?)([0-9]+)$/.exec(i);//正则表达式抓取正负符号和数字的文本值
            if(regR !== null){
                var nstr = regR[2];//数字的文本值,相当于Java的group(2)
                var nstrlen = nstr.length;
                var nResult = arguments.callee(0);//callee就是本function
                for(idx in nstr){
                    //通过计算ASCII码的差值转换成数字, 见后记
                    nResult += (nstr[idx].charCodeAt(0) - "0".charCodeAt(0)) * 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;
        }
    }

 

 

后记: string快速转换成number的方法是 "123" * 1 = 123 , 但这是语法糖, 实际上是 Number("123") * 1 

 

Number()和new Number()的区别以及造个简单的轮子

标签:简单   false   tostring   height   code   except   body   obj   value   

原文地址:https://www.cnblogs.com/DebuggerWei/p/8330866.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!