美文网首页
Chapter 22. 高级技巧篇

Chapter 22. 高级技巧篇

作者: weiee | 来源:发表于2018-08-07 20:30 被阅读0次

    js中所有的function都是对象,可以利用指针搞事情。

    1. 安全的类型检测:
      typeof不可靠,比如正则类型可能返回"function"。instanceof在存在多个全局作用域情况下(例如多个frame)也不可靠。如何检测某个对象是原生对象还是开发者自定义对象?
      以上答案:
      通过调用Object对象的原生方法toString,能返回[object NativeConstructorName],每个对象有个内部属性[[Class]],其值为构造器的名称。
      例:var x = "abc";
      var type = Object.prototype.toString.call(x); //type的值为"[object String]"
      Object的toString方法不能检测非原生构造函数的构造函数名,因此自定义的任何构造函数都将返回[object Object]。
      注意:Object的toString方法本身可能被篡改!
    2. 作用域安全的构造器:
      构造器就是使用new操作符的函数,构造器内的this对象指向新创建的对象实例。如果忽略new操作符,内部的this指针绑定到运行时的window对象,可能导致错误。因此需要作用域安全的构造器。
      使用作用域安全的构造器首先要判断this对象是否是该构造器的实例。
      注意:如果使用作用域安全的构造器,则会锁定调用构造器的环境。如果使用构造器窃取(constructor-stealing)模式的继承而不使用原型链,则继承可能被破坏。
      解决方式:构造函数窃取模式结合原型链(prototype chain)或寄生组合(parasitic combination)。
    3. 惰性加载函数:
      问题:避免每次判断不必要的if语句。
      惰性加载表示函数执行的分支只发生一次。两种实现方式:1.在函数首次执行时处理,该函数被覆盖为按合适方式执行的函数,方便未来调用不经过条件分支,会在首次执行时损失性能;2.在函数声明时处理,通过匿名函数方式返回合适的执行函数,代码首次加载时会损失性能。
    4. 函数绑定:
      创建一个可以通过特定的this值和特定的参数调用另一个函数的函数。常与回调和事件处理器一起使用,以便将函数作为变量传递时同时保留代码执行环境。
      方式:1.闭包;2.创建将函数绑定到指定环境的函数。
      js库提供可将函数绑定到指定环境的函数:bind(),bind()函数创建一个闭包,闭包通过使用apply()调用传入的函数fn,并给apply()传递上下文对象(context)和arguments参数。注意:arguments参数是返回的匿名函数的参数,不是bind的参数。
      function bind(fn, context){
      return function(){
      return fn.apply(context, arguments);
      };
      }
      ES5为所有函数定义了原生的bind()方法:fn.bind(context)。传入上下文对象(context)作为this值。被绑定函数与普通函数相比有更多开销,因为函数的多重调用需要更多内存。
    5. 函数柯里化(Currying):
      柯里化定义:柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后,部分应用参数,并返回一个更具体的函数接受剩下的参数,中间可嵌套多层这样的接受部分参数函数,逐步缩小函数的适用范围,逐步求解,直至返回最后结果。
      js的函数柯里化用于创建已经设置好了1个或多个参数(部分函数应用)的函数。基本思路与函数绑定相同:使用闭包返回一个函数。区别:当柯里化后的函数被调用时,需要设置传入参数。
      ES5的bind()函数已实现函数柯里化,只要在this后传入参数即可。
    function bind(fn, context) {
        return function() {
            return fn.apply(context, arguments);
        }
    }
    
    function curry(fn) {
        var _arg = Array.prototype.slice.call(arguments, 1);
        return function () {
            return fn.apply(null, _arg.concat(Array.prototype.slice.apply(arguments)));
        }
    }
    
    //方式1
    function sum() {
        var sum = 0;
        var _arg = Array.prototype.slice.apply(arguments);
        for (var i = 0; i < _arg.length; i++) {
            sum += _arg[i];
        }
        return function() {
            var _innerArg = Array.prototype.slice.apply(arguments);
            if (_innerArg.length > 0) {
                for (var i = 0; i < _innerArg.length; i++) {
                    sum += _innerArg[i];
                }
                return arguments.callee;
            } else {
                return sum;
            }
        }
    }
    var x = sum(1,2,3)(0)(3,4,5)();
    console.log(x);
    
    //方式2
    function currySum(fn) {
        var _args = [];
        return function() {
            var _innerArg = Array.prototype.slice.apply(arguments);
            if (_innerArg.length === 0) {
                return fn.apply(null, _args);
            } else {
                _args = _args.concat(_innerArg);
                return arguments.callee;
            }
        }
    }
    function sum2() {
        var _arg = Array.prototype.slice.apply(arguments);
        var sum = 0;
        for (var i = 0; i < _arg.length; i++) {
            sum += _arg[i];
        }
        return sum;
    }
    var currideSum = currySum(sum2);
    var z = currideSum(0,1)(2,3,4,5)(2)(3)();
    console.log(z);
    
    function sqr(i) {
        return i*i;
    }
    
    function map(hdl, list) {
        return list.map(hdl);
    }
    
    var mapSqr = curry(map, sqr);
    
    

    相关文章

      网友评论

          本文标题:Chapter 22. 高级技巧篇

          本文链接:https://www.haomeiwen.com/subject/dtqzvftx.html