最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js高阶编程技巧

    正文概述 掘金(极致同学)   2020-12-24   290

    js高阶编程技巧

    js高阶编程技巧的核心就是利用闭包,实现一些高阶编程的方式 那么,属于js高阶编程方式都有哪些呢?

    模块化思想

    模块化思想的发展经过了单例模式->AMD->CMD->CommonJS->ES6Moudle几个里程碑 在js中,模块化思想的好处就是便于封装,在协同工作的模式下,保护了各个人员之间的代码与全局作用域中的变量不互相污染。

    (function(){
        let time=0;
        function changeTime(){
            time++;
        }
    })();
    

    上面的代码使用闭包的方式实现了对其的保护,不会污染全局变量

    (function(){
        let time=0;
        function changeTime(){
            time++;
        }
        window.changeTime=changeTime;
    })();
    

    window.changeTime=changeTime;将方法changeTime暴露给全局作用域,以供他人调用。但是如果挂载的过多,就会可能造成污染

    js对象的特点是,每一个对象都是一个单独的堆内存空间

    仿照其他后台语言,其实obj1,obj2不仅仅是对象名,还被成为命名空间

    每一个对象都是一个单独的实例,用来管理自己的私有信息,即使名字相同,也互不影响,其实这就是js中的单例模式

    var obj1={
        name:"rose",
        age:18,
        fn:function(){
            //.....
        }
    }
    var obj2={
        name:"jack",
        age:18,
        fn:function(){
            //.....
        }
    }
    

    前面的解决

    var Time = (function(){
        let time=0;
        function changeTime(){
            time++;
        }
        return{
            changeTime
        }
    })();
    //自执行函数执行之后返回一个对象被Time引用,其开辟的栈内存空间不能释放,形成了一个闭包。外界想要调用changeTime方法的时候,直接使用Time.changeTime即可,这样就不会污染全局环境。
    

    以上模式就是高级单例设计模式(闭包+单例)也是最早期的js模块化思想。

    惰性函数

    惰性函数就是懒的意思,想要代码尽量少,执行尽量少,内存消耗尽量少。

    例如:

    返回样式对象的api window.getComputedStyle(),但是这个api并不兼容ie,ie中有自己的api dom.currentStyle()来获取样式对象。

    function getCss(element,attr){
        if("getComputedStyle" in window){
             return window.getComputedStyle(element)[attr];
        }
        return element.currentStyle[attr];
    }
    

    但是,我们在每次使用 getCss()这个函数的时候,就会执行一次getComputedStyle" in window,我们知道,我们没有换浏览器,所以每次执行的结果都相同,再次执行getComputedStyle" in window,没有必要,惰性思想要做的就是能一次解决的事情,不会再做第二次。

    优化:

    let flag="getComputedStyle" in window
    function getCss(element,attr){
        if(flag){
             return window.getComputedStyle(element)[attr];
        }
        return element.currentStyle[attr];
    }
    

    但是这个flag变量进入全局变量空间了,通过学习前面的单例模式,我们知道这样写其实不太好。接下来,看下面的代码。

    再优化

    let getCss=function (element,attr){
        if("getComputedStyle" in window){
            getCss = function(element,attr){
                return window.getComputedStyle(element,attr);
            }	
        }else{
            getCss = function(element,attr){
            	return element.currentStyle[attr];
        	}
        }
    }
    

    这样我们发现第一次执行并不会出效果。再优化

    let getCss=function (element,attr){
        if("getComputedStyle" in window){
            getCss = function(element,attr){
                return window.getComputedStyle(element,attr);
            }	
        }else{
            getCss = function(element,attr){
            	return element.currentStyle[attr];
        	}
        }
        return getCss(element,attr)
    }
    

    结束!

    柯里化函数

    是一种预先处理的思想,形成一个闭包,将一些值(未来会使用)保存起来。所有符合这种模式的,都叫做柯里化函数。

    下面我们以一道题展开:

    // 普通的add函数
    function add(x, y) {
        return x + y
    }
    add(1, 2)           // 3
    curryingAdd(1)(2)()   // 3
    

    要实现上面代码中的效果,curryingAdd函数要如何编写呢

    上面我们说到,函数柯里化是用闭包将一些值保存起来以供未来使用。

    function curryingAdd(...params) {
      let args = [...params];
      return function inner(...arguments) {
        args = args.concat(arguments);
        return eval(args.join("+"));
      };
    }
    console.log(curryingAdd(1, 2)());//3
    console.log(curryingAdd(1, 1)(1, 1);//4
    

    这里,我们将传进来的值放进数组args中保存,返回一个函数inner,这样就可以二次调用。那么如何实现三次甚至四次多次连续不定次调用呢?比如

    console.log(curryingAdd(1, 1)(1, 1)(2, 2)());//8
    

    这时我们就需要再inner函数中做一些处理,如下所示:

    function curryingAdd(...params) {
      let args = [...params];
      return function inner(...arguments) {
        args = args.concat(arguments);
        if (arguments.length == 0) {
          return eval(args.join("+"));
        } else {
          return inner;
        }
      };
    }
    console.log(curryingAdd(1, 2)());
    console.log(curryingAdd(1, 1)(1, 1)());//4
    console.log(curryingAdd(1, 1)(1, 1)(2, 2)());//8
    

    我们通过判断inner函数值的有无来判断是返回结果还是继续返回函数。如果arguments参数长度为0,说明已经没有参数可以使用了,那么返回args中值相加的结果,如果arguments中仍旧有参数,那么就返回函数inner,以供接着向args中追加参数。

    compose组合函数

    在函数式编程中有一个很重要的概念就是函数组合,实际上就是把处理函数像管道一样连接起来。然后让数据穿过管道得到最终的结果。例如:

    const add1=(x)=>x+1;
    const mul3=(x)=>x*3;
    const div2=(x)=>x/2;
    div2(mul3(add1(add1(0))))//=>3
    

    上面的那中写法可读性明显太差了,我们可以构建一个compose函数,它接收任意多个函数作为参数(这些函数都只接受一个参数),然后compose函数返回的也是一个函数,达到以下的效果。

    const operate=compose(div2,mul3,add1,add1);
    operate(0)//相当于div2(mul3(add1(add1(0))))//=>3
    operate(2)//相当于div2(mul3(add1(add1(2))))//=>3
    

    那么compose函数应该怎样写呢?

    const add1 = (x) => x + 1;
    const mul3 = (x) => x * 3;
    const div2 = (x) => x / 2;
    function compose(...funs) {
      return function(arg) {
        for (let i = funs.length - 1; i >= 0; i--) {
          arg = funs[i](arg);
        }
        return arg;
      };
    }
    let operate = compose(div2, mul3, add1, add1);
    console.log(operate(0));//3
    

    同样是使用闭包的思想,将存储进去的函数保存起来,待operate()调用的时候就可以使用保存的函数进行运算。返回运算结果。

    优化:

    const add1 = (x) => x + 1;
    const mul3 = (x) => x * 3;
    const div2 = (x) => x / 2;
    function compose(...funs) {
      return function(arg) {
        if (funs.length === 0) return arg;
        for (let i = funs.length - 1; i >= 0; i--) {
          if (typeof funs[i] != "function") continue;
          arg = funs[i](arg);
        }
        return arg;
      };
    }
    let operate = compose(div2, mul3, add1, add1);
    console.log(operate(0));
    

    另外一种实现方案

    const add1 = (x) => x + 1;
    const mul3 = (x) => x * 3;
    const div2 = (x) => x / 2;
    function compose(...funs) {
      if (funs.length === 0) {
        return (arg) => arg;
      }
      if (funs.length == 1) {
        return funs[0];
      }
      //a:初始值或者计算结束后返回的值,b当前值
      return funs.reduce((a, b) => {
        return (...args) => a(b(...args));
      });
    }
    let operate = compose(div2, mul3, add1, add1);
    console.log(operate(0));//3
    
    

    起源地下载网 » js高阶编程技巧

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元