• 第七课:数值以及函数的扩展和修复


    1.数值扩展和修复

    toFixed(num) 方法可把 Number 四舍五入为指定小数位数的数字。num必需,规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。返回 NumberObject 的字符串表示,不采用指数计数法,小数点后有固定的 num 位数字。如果必要,该数字会被舍入,也可以用 0 补足,以便它达到指定的长度。如果 num 大于 le+21,则该方法只调用 NumberObject.toString(),返回采用指数计数法表示的字符串。

    但在有些浏览器下不会这样干,于是修复:

    if(0.9.toFixed(0) !=='1'){

      Number.prototype.toFixed = function(n){    

        var power = Math.pow(10,n);    //Math.pow(x,y),返回 x 的 y 次幂的值

        var fixed = (Math.round(this*power) / power).toString();    //把一个数字舍入为最接近的整数。比如:0.5->1,0.4->0

        if(n == 0)  return fixed;      //当n等于0时,就直接调用round方法,把num四舍五入为最接近num的整数

        if(fixed.indexOf('.')<0)  fixed + = '.';        //如果是整数,并且n>0,那么需要添加n位小数。所以先添加小数点.

        var padding = n+1 - (fixed.length - fixed.indexOf('.'));    //小数点后面必须有n个数字。没有就用0填补

        for(var i=0;i<padding;i++)  fixed + = '0';     //假设fixed为12.2,n为3,那么fixed.length=4,fixed.indexOf('.')=2,则padding = 4-2 =2;return 12.200

        return fixed;                                                   

      }

    }

    当javascript遇到一个数值时,它会首先尝试按照整数来处理该数值,如行得通,则把数值保存为31位的整数;如果该数值不能视为整数,或者超过31位的范围,则把数值保存为64位的IEEE754浮点数。

    最大的Unicode值是1114111,最大的RGB颜色值是16777215(相当于#FFFFFF)。最大的10位数字是Math.pow(2,31)-1.最小的10位整数是-Math.pow(2,31)。

    因此,js内部会以整数的形式保存所有Unicode值和RGB颜色。

    我们尽量在前端只处理以整数形式保存的数字,大数和小数的操作尽量交给后台处理,实在避免不了,就用专业的库来处理。

    2.函数的扩展与修复

    bind函数:改变函数执行的上下文。低版本浏览器不支持,需要扩展。

    Function.prototype.bind = function(context){

      if(arguments.length < 2 && context == undefined){  

        //当传入的参数1个或者0个,并且第一个参数为undefined时(其实就是没传入context,或者传入一个undefined的context),就返回this,也就是函数本身

        return this;      //当方法say.bind(undefined,chaojidan),这种情况下,不会返回this,而是把chaojidan这个参数保存下来,之后会作为参数传到方法say中去。

      }

      var _method = this,args = [].slice.call(arguments,1);

      return function(){

        return _method.apply(context,args.concat.apply(args,arguments));      

          //此函数在传入的context上下文中执行。并且把bind传入的参数和函数本身传入的参数合并成一个数组传入函数中执行。

      }

    }

    这个方法用的最多的是在IE下添加事件时,this的指向问题。IE的API attachEvent在回调中的this指向window.

    var addEvent = document.addEventListener ? functon(el,type,fn,capture){  

        el.addEventListener(type,fn,capture)  ;

      } : function(el,type,fn){

        el.attachEvent("on"+type, fn.bind(el));     //把this指向了el元素

      }

    apply方法第二个参数一定要是数组或者arguments这样的类数组(jQuery对象{0:"0",1:"1",length:2}也是类数组)。(NodeList这样的传进去在有些浏览器会出问题,因此jQuery中是使用merge来处理数组的合并,而不是使用Array.prototype.push.apply来处理,当然slice,concat这类的数组方法在有些浏览器下也不能很好的处理NodeList)。

    hasOwnProperty判断是否是对象的实例属性,而不是原型属性。

    bind方法着重于作用域的劫持,改变方法执行时的上下文。

    curry 函数柯有化在于参数的不断补充,它可以给你再一次传参的机会,这样你就可以在内部判定参数的个数,决定是否继续返回函数还是结果。这在设计计算器的连续运算上非常有用。举个例子:function curry (fn){   

              function inner(len,arg){  

                if(len<=0)  return fn.apply(null,arg);  

                return function(){  return inner(len-arguments.length,arg.concat(Array.apply([],arguments)))  }  

              }   

              return inner(fn.length,[]); 

           }

    function sum(a,b,c,d){  return a+b+c+d;  }

    curry(sum)('a')()('b','c')('d')       //return 'abcd';

    这种自身调用自身来补全参数的,叫做self-curry或者recurry。

    与curry相似的partial。curry的不足是参数总是通过push的方式来补全,而partial则是在定义时所有参数已经都有了,但某些位置上的参数只是一个占位符,我们在接下来的传参只是替换掉它们。

    Function.prototype.partial = function(){

      var fn = this, args = Array.prototype.slice.call(arguments);

      return function(){

        var arg = 0;

        for(var i=0;i<args.length&&arg<arguments;i++ ){

          if(args[i] == undefined){

            args[i] = arguments[arg++];

          }

        }

        return fn.apply(this,args);

      }

    }

    这里是使用undefined作为占位符。

    比如:var delay = setTimeout.partial(undefined,10);     ->  fn = setTimeout

    delay(function(){});      //执行时,会先执行for循环,把partial中的参数遍历,如果有undefined,就用delay中的参数代替,因此这里会用function代替undefined。这时return setTimeout.apply(this,[function,10])。

    对于占位符,我们可以使用一个纯空对象:

    var _ = Object.create(null);      //纯空对象没有原型,没有toString,valueOf等继承自Object的方法。

    另外一种实现方法:

    function partial(fn){

      var A = [].slice.call(arguments,1);     //数组化

      return A.length < 1? fn : function(){

        var a = Array.apply([],arguments);    //数组化

        var c = A.concat();       //复制一份

        for(var i =0;i<c.length;i++)  if(c[i] === _)  c[i] = a.shift();

        return fn.apply(this,c.concat(a));    

      }

    }

    function test(a,b,c,d){  return a+b+c+d;  }

    var fn = partial(test, 1, _,2,_);        //这里的意思就是,方法test需要传入4个参数,目前只传入了两个。其他两个用_来占位。

    fn(4,5)      //再传入两个参数,传参结果是(1,4,2,5),然后返回执行test的方法。

    curry和partial的应用场景比较少,主要使用在异步上。比如:Ajax的异步函数回调嵌套问题,就可以使用curry将嵌套减少可以接受的范围。

    加油!

  • 相关阅读:
    进程相关知识点
    vue上传
    Storageclass 外挂NFS配置与应用
    centos强制关机后,网卡无法启动
    前端工程化2-webpack使用与学习
    android应用获取应用签名
    js获取tif格式图片的dpi
    查询生成二级树型结构最高效的方式
    03解决隔离的方案
    02SingleSpa实战
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4135124.html
Copyright © 2020-2023  润新知