JS 精粹( 函数)

    函数是对象,它与其它对象唯一的不同是它可以调用。函数可实现:代码复用、信息隐藏、代码组合调用。

    建立函数时会建立:上下文、调用函数的代码。每个函数(除Function.prototype)都会有一个原型对象。

   function foo ( ) {
     //code
}

foo.prototype = {constructor:this};

    它必有一个foo.prototype对象,而且这是显含的。

    函数字面量属于字面量,也就属于表达式的范畴。从而可以使用表达式的地方就可以使用函数字面量。

    JS函数的参数是按值传递的。它不会检查传入实参的类型、个数;若实参少于形参实参函数调用时的形参值为undefined.每个函数会this,this在函数执行时才会确定,与函数的调用方式相关(与动态作用域有某种相似)。调用方式分为:方法调用、函数调用、构造器调用、apply调用。

   

    方法调用:也就是说一个函数为某个对象的属性值。那么函数调用时的this到底是哪个?

          我要再次强调,对象会有自己默认的原型链,同时我们可以设置对象的prototype属性,但这个属性与内部的原型链相比很弱,对象的"继承"或更确切的说是委托是基于内部原型链的。

   var a = {};
   var b = {"name":"name"};
    a.prototype = b;
   console.log(a.name)    //undefined


    Object.setPrototypeOf(a,b);
     console.log(a.name)   //"name"

   开始,我直接设置prototype属性,然后以为通过对象的继承可以访问到对象b中的name;事实是:此时a与b的原型链链接到了Object.prototype。

   接着,我真正修改了原型链,故可以访问到name属性。

 

   那么,这个表面的prototype有何用?

        前文提到函数(除Function.prototype)总会有一个对象与之对应。若我建立一个用函数建立一个对象的话,就会有用。新建的对象的原型链中的上一环为构造函数的prototype对象。

 function foo () {}
//那么一定有一个foo.prototype对象。
var  b = new foo();
该对象的原型链中就会有 b 的存在
  foo.prototype.isPrototypeOf(b) //true

     其三,一般函数的原型链中不含prototype对象。但Function.prototype为function(){},且位于Function的原型链中。

              Function.prototype.isPrototypeOf(Function)        //true.

 

      回到刚才的问题,方法调用函数时,对应的this为何值。我直接给出结论,我认为是:可以直接查找到方法的那个对象。直接上代码。

     

   var a = {"a":"a"};
        var b = {"b":"b"};
        var c = {"c":"c",
                 "show":function(){
                     return this;
                 }
             };
         Object.setPrototypeOf(b,c);
         Object.setPrototypeOf(a,b);   
     //现在原型链从a开始到b到c到Object.prototype.
 
          a.show();         //对象a
          b.show();        //对象b
    

   //Function的例子
    
     Function.prototype.method = function (name,func) {
            this.prototype[name] = func;
              return this; 
};
        //  this与调用方式有关

       干脆更加明白一些。

   Function.prototype  //    function () {}
   Function.protoype.demo = function () {
                console.log(this); 
};

  //可以通过Function这个函数访问到demo方法,
    
      Function.demo()        // function    Function() { [native code] }
      
       Function.prototype.demo()    //  function () {}

                  所以,不是方法在那个对象中this就是哪个。

 

    函数调用的时候的this值。

            直接调用函数是this是全局对象而非该函数的外围的this值,ES6中有语法糖来处理这个问题。

    构造函数模式的this

          new + 构造函数会形成一个对象,这里忽略其他细节;只讲this值,这时的this是新建立的那个对象。还是举个栗子。

   function foo (name) {
                  this.name = name;
}
 
   var obj = new foo ();
   
//也就是说foo执行时的this是obj,从而才有给obj添加name属性的可能
 

      构造函数与一般函数没有区别,但是若一个函数建立的目的是用于建立对象,应当把其首字母大写;否则直接调用可能会给全局对象添加属性。

     apply调用模式

            函数是对象,所以可以有方法,apply/call就是方法。伪代码:function.apply(this,argumnets),function.call(this,p1,p1,p1)。

记忆

     记忆这种优化手段真是让人兴奋,它可以大大减少计算的工作量,例如在阶乘、裴波那契数列的计算中,若不采用优化,那浏览器甚至算不出来。采用优化后秒算出结果。下面是通用的记忆器。

 function memoizer (memo,formula) {
        var recur = function (n) {
                 var result = memo[n];
                if ( typeof result !== "number") {
 
                     result = formula();
                memo[n] = result;
           }
            return result;   

        }
    return recur;
}

      JS的函数化很强大,这种方法在一个个函数的基础上差异化继承,也可以增强;也是建立部件的基础。实现对象与它的功能模块的扩充。建立对象与方法之间的松散耦合。

    var o = {name:"demo"};
    var enhance = function (o) {
                var that = o;
                 if ( !o.name) {
                         o.name = "initial"; 
          } 
                 if ( !o.get_name) {
                          o.get_name = function () {
                                 return o.name;    
                                   };              
         }
           return that;
};
    var  b =  enhance(o);

 

posted @ 2016-09-08 11:42  月下夜行  阅读(177)  评论(0)    收藏  举报