首页 > 代码库 > Javascriptg高级函数

Javascriptg高级函数

Javascript高级函数

  • 惰性载入函数
  • 函数柯里化
  • 级联函数

这并不全面,只是几个主要的。

惰性载入函数

  惰性载入表示函数执行的分支只会在函数第一次掉用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。

  写一个函数用来创建XmlHttpRequest对象,浏览器兼容性原因,写出的代码通过大量if判断或者try,catch语句将函数引导到正确代码处。

代码示例:

function createXHR(){
    var xhr = null;
    try {
        // Firefox, Opera 8.0+, Safari,IE7+
        xhr = new XMLHttpRequest();
    }
    catch (e) {
        // Internet Explorer 
        try {
            xhr = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {
                xhr = null;
            }
        }
    }
    return xhr;
} 

  每次调用这个函数的时候,都要先进行浏览器能力检查,首先检查浏览器是否支持内置的XMLHyypRequest对象,如果不支持然后检查各版本基于ActiveX的XMLHttpRequest,每次调用该函数都是这样,其实当第一次执行完后,如果浏览器支持某个特定XMLHttpRequest对象,那么下次执行的时候这种支持性并不会改变,没必要再进行一边检测,即使只有一个if语句,执行也肯定比没有要慢,如果我们可以让if语句不必每次执行,那么就可以在频繁调用的情况下提高执行速度。并且如果在多次createXHR后没有处理好,还会非常容易造成内存泄漏。解决方案就是惰性载入。在已经判断出当前浏览器是什么的时候,就让createXHR == XHR; 

function createXHR(){
  var xhr=null;
  if(typeof XMLHttpRequest !=‘undefined‘){   xhr = new XMLHttpRequest(); createXHR=function(){   return new XMLHttpRequest(); } }else{   try {   xhr = new ActiveXObject("Msxml2.XMLHTTP"); createXHR=function(){   return new ActiveXObject("Msxml2.XMLHTTP"); } } catch (e) {   try {   xhr = new ActiveXObject("Microsoft.XMLHTTP"); createXHR=function(){   return new ActiveXObject("Microsoft.XMLHTTP"); } } catch (e) {   createXHR=function(){ return null; } } } } return xhr; }

  在这个惰性载入的createXHR中第一次执行的时候每个分支都会为createXHR重新赋值,覆盖原函数,返回xhr对象,而第二次执行的时候就会直接调用重写后的函数,这样就不必执行每个分支重新做检测了。

函数柯里化

  在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

  说起函数柯里化,我理解起来确实费了很大一波力,首先对于代码中的很多部分都不理解,比如slice、call()、apply()【日后会写这三个】。理解了这些之后自然能够看懂柯里化的通用实现:

代码示例:

function currying(fn) {
    var args = Array.prototype.slice.call(arguments, 1);
    return function () {
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = args.concat(innerArgs);
        console.log (finalArgs);
        return fn.apply(this,finalArgs);
    };
}
    1. 提高适用性

      代码示例:

      function square(i) {
          return i * i;
      }
      
      function dubble(i) {
          return i *= 2;
      }
      
      function map(handeler, list) {
          return list.map(handeler);
      }
      
      // 数组的每一项平方
      map(square, [1, 2, 3, 4, 5]);
      map(square, [6, 7, 8, 9, 10]);
      map(square, [10, 20, 30, 40, 50]);
      // ......
      
      // 数组的每一项加倍
      map(dubble, [1, 2, 3, 4, 5]);
      map(dubble, [6, 7, 8, 9, 10]);
      map(dubble, [10, 20, 30, 40, 50]);
      

      例子中,创建了一个map通用函数,用于适应不同的应用场景。。同时,例子中重复传入了相同的处理函数:square和dubble。

      应用中这种需要处理的东西会更多。通用性的增强必然带来适用性的减弱。但是,我们依然可以在中间找到一种平衡。

      看下面,我们利用柯里化改造一下:

      代码示例:

      function square(i) {
          return i * i;
      }
      
      function dubble(i) {
          return i *= 2;
      }
      
      function map(handeler, list) {
          return list.map(handeler);
      }
      
      var mapSQ = currying(map, square);
      mapSQ([1, 2, 3, 4, 5]);
      mapSQ([6, 7, 8, 9, 10]);
      mapSQ([10, 20, 30, 40, 50]);
      // ......
      
      var mapDB = currying(map, dubble);
      mapDB([1, 2, 3, 4, 5]);
      mapDB([6, 7, 8, 9, 10]);
      mapDB([10, 20, 30, 40, 50]);
      // ......
      

      柯里化降低通用性,提高适用性。  

    2. 延迟执行

      不断的柯里化,累计传入的参数,最后执行。

      代码示例:

      var add = function() {
          var _this = this,
          _args = arguments
          return function() {
              if (!arguments.length) {
                  var sum = 0;
                  for (var i = 0,c; c = _args[i++];) sum += c;
                  return sum;
              } else {
                  Array.prototype.push.apply(_args, arguments) 
      return arguments.callee; } } } add(1)(2)(3)(4)();//10

      柯里化:

      var curry = function(fn) {
          var _args = []
          return function cb() {
              if (arguments.length == 0) {
                  return fn.apply(this, _args)
              }
              Array.prototype.push.apply(_args, arguments);
              return cb;
          }
      }
      

        

    3. 固定易变因素

      柯里化特性决定了它可以提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。

      Function.prototype.bind = function(context) {
          var _this = this,
          _args = Array.prototype.slice.call(arguments, 1);
          return function() {
              return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments)))
          }
      }
      

但其实我还是没有那么透彻的理解函数柯里化,应该等到其他的知识掌握的更加熟练,理解起来也才会更加容易吧

级联函数

  级联函数也叫链式函数,方法链一般适合对一个对象进行连续操作(集中在一句代码),一定程度上把相关的属性都连到一起,减少代码量,缺点是它占用了函数的返回值。

function myclassA(){
 this.name="";
 this.age="";
 this.sex="";
}
myclassA.prototype={
 setname:function(){
  this.name="katherine";
  return this;
 },
 setage:function(){
  this.age="22";
  return this;
 },
 setsex:function(){
  this.sex=‘girl‘;
  return this;
 }
}
var me =new myclassA();
console.log(me.setname().setage().setsex());

// myclassA {name: "katherine", age: "22", sex: "girl"}

  这一篇整整弄了两天才弄完,但是还是有些搞不懂函数柯里化,我想只能在日后的开发中,慢慢接触项目来解锁理解了【摊手】

 

  

Javascriptg高级函数