javascript高级知识点——函数的长度

代码信息来自于http://ejohn.org/apps/learn/。

函数的长度属性如何工作?

function makeNinja(name){} 
function makeSamurai(name, rank){} 
console.log( makeNinja.length == 1, "只定义了一个形参" ); 
console.log( makeSamurai.length == 2, "定义了两个形参" );

很清楚,函数的长度就是定义形参的个数。

我们可以利用这一点写重载函数

function addMethod(object, name, fn){ 
  // 存储对过去方法的引用
  var old = object[ name ]; 
 
  // 重写新的方法
  object[ name ] = function(){ 
    // 核对定义形参的个数, 
    // 与我们接受接收参数的个数
    if ( fn.length == arguments.length ) 
      // 如果匹配运行这个函数
      return fn.apply( this, arguments ); 
 
    // 否则调用过去的方法
    else if ( typeof old === "function" ) 
      return old.apply( this, arguments ); 
  }; 
}

来看一看重载函数的运用

function addMethod(object, name, fn){ 
  // 存储对过去方法的引用
  var old = object[ name ]; 
 
  // 重写新的方法
  object[ name ] = function(){ 
    // 核对定义形参的个数, 
    // 与我们接受接收参数的个数
    if ( fn.length == arguments.length ) 
      // 如果匹配运行这个函数
      return fn.apply( this, arguments ); 
 
    // 否则调用过去的方法
    else if ( typeof old === "function" ) 
      return old.apply( this, arguments ); 
  }; 
}
 
function Ninjas(){ 
  var ninjas = [ "Dean Edwards", "Sam Stephenson", "Alex Russell" ]; 
  addMethod(this, "find", function(){ 
    return ninjas; 
  }); 
  addMethod(this, "find", function(name){ 
    var ret = []; 
    for ( var i = 0; i < ninjas.length; i++ ) 
      if ( ninjas[i].indexOf(name) == 0 ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
  addMethod(this, "find", function(first, last){ 
    var ret = []; 
    for ( var i = 0; i < ninjas.length; i++ ) 
      if ( ninjas[i] == (first + " " + last) ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
} 
 
var ninjas = new Ninjas(); 
console.log( ninjas.find()); 
console.log( ninjas.find("Sam")); 
console.log( ninjas.find("Dean", "Edwards")); 
console.log( ninjas.find("Alex", "X", "Russell"));

实例化ninja时,向ninja执行了4次添加方法,每次都覆盖在find属性上,根据闭包的作用域链,新的方法仍然可以引用addMethod里old,old保存的是上一个方法。

最后的find就是判断参数,与形参数量是否相同,是就执行,不是就调用old的方法。如此反复。

等同于以下代码

var ninjas = {
    find: function(){
        var ninjas = [ "Dean Edwards", "Sam Stephenson", "Alex Russell"] 
        var old = function(){
            var ninjas = [ "Dean Edwards", "Sam Stephenson", "Alex Russell"] 
            var old = function(){
                var ninjas = [ "Dean Edwards", "Sam Stephenson", "Alex Russell"] 
                var old;
                var fn =   function(){ 
                    return ninjas; 
                  }
                if ( fn.length == arguments.length ) {
                  return fn.apply( this, arguments ); 
                }else if ( typeof old === "function" ) {
                  return old.apply( this, arguments ); 
                }
            };
            var fn =  function(name){ 
                var ret = []; 
                for ( var i = 0; i < ninjas.length; i++ ) 
                  if ( ninjas[i].indexOf(name) == 0 ) 
                    ret.push( ninjas[i] ); 
                return ret; 
              }
            if ( fn.length == arguments.length ) {
              return fn.apply( this, arguments ); 
            }else if ( typeof old === "function" ) {
              return old.apply( this, arguments ); 
            }
        }
        var fn =  function(first, last){ 
            var ret = []; 
            for ( var i = 0; i < ninjas.length; i++ ) 
              if ( ninjas[i] == (first + " " + last) ) 
                ret.push( ninjas[i] ); 
            return ret; 
        }
        if ( fn.length == arguments.length ) {
          return fn.apply( this, arguments ); 
        }else if ( typeof old === "function" ) {
          return old.apply( this, arguments ); 
        }
    },
}
console.log( ninjas.find()); 
console.log( ninjas.find("Sam")); 
console.log( ninjas.find("Dean", "Edwards")); 
console.log( ninjas.find("Alex", "X", "Russell"));