权威指南学习心得-函数

函数javascript

形参在函数中像局部变量同样工做。java

函数使用它们实参的值来计算返回值,成为该函数调用表达式的值。除了实参以外。每次调用还会拥有另外一值-本次调用的上下文-这就是this关键字的值数组

若是函数挂载在一个对象上,做为对象的一个属性,就称它为对象的方方法。当经过这个对象来调用函数时,该对象就是这次调用的上下文,也是改函数的this的值。用于初始化一个新建立的对象的函数称为构造函数闭包

若是一个函数定义表达式包含名称,函数的局部做用域将会包含一个绑定到函数对象的名称,实际上函数的名称将成为函数内部的一个局部变量app

function f(){
  console.log(f);
}
f();//

function f(){
window.runnerWindow.proxyConsole.log(f);
}函数

var t=function test(){
  console.log(t);//

function test(){
window.runnerWindow.proxyConsole.log(t);
window.runnerWindow.proxyConsole.log(test);
}this


  console.log(test);//

function test(){
window.runnerWindow.proxyConsole.log(t);
window.runnerWindow.proxyConsole.log(test);
}spa


};
t();

函数声明语句被提早到外部脚本或外部函数做用域的顶部,因此以这种方式声明的函数,能够被在它定义以前出现的代码所调用,以表达式定义的函数就另当别论了,为了调用一个函数,必需要能引用它,而要使用一个以表达式定义的函数以前,必须把它赋值给一个变量。变量的声明提早了,可是被变量赋值是不会提早的,因此,以表达式方式定义的函数在定义以前是没法调用的prototype

有4种方法来调用javascript函数code

做为函数

做为方法

做为构造函数

经过它们的call和apply方法间接调用

关键值this没有做用域的限制,嵌套的函数不会从调用它的函数中继承this。若是嵌套函数做为方法调用,其this的值指向调用它的对象。若是嵌套函数做为函数调用。其this是全局对象

var o={m:function(){
  var self=this;
  console.log(this===o);//true
  f();
  function f(){
    console.log(this===o);//false
    console.log(self===o);//true
    
  }
  
}};
o.m();

若是函数或者方法调用以前带有关键字new,它就构成构造函数调用

构造函数调用建立一个新的空对象,这个对象继承自构造函数的prototype属性,构造函数试图初始化这个新建立的对象,并将这个对象用作其调用上下文,所以构造函数可使用this关键字来引用这个新建立的对象。注意,尽管构造函数看起来像一个方法调用,但它依然会使用这个新对象做为调用上下文。也就是说,在表达式new o.m()中,调用上下文并非o。

构造函数一般不使用return关键字,它们一般初始化新对象,当构造函数的函数体执行完毕时,它会显示返回。在这种状况下,构造函数调用表达式的计算结果就是这个新对象的值。然而若是构造函数显式的使用return语句返回一个对象,那么调用表达式的值就是这个对象。若是构造函数使用return语句但没有指定返回值或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象做为调用结果。

可选形参

function getPropertyNames(o,a){
  a=a||[];
  for(var property in o){
    a.push(property);
  }
  return a;
}

var o={x:1,y:2};

var test=getPropertyNames(o);
console.log(test);//["x", "y"]
function max(){
  var  result=Number.NEGATIVE_INFINITY;
  for(var i=0;i<arguments.length;i++){
    if(arguments[i]>result){
      result=arguments[i];
    }
  }
  return result;
  
}

console.log(max(4,1,8));//8

当一个函数包含若干形参。实参对象的数组元素是函数形参所对应实参的别名,实参对象中以数字索引,而且形参名称能够认为是相同变量的不一样命名。经过实参名字来修改实参值的话,经过arguments[]数组也能够获取到更改后的值

arguments.callee和arguments.caller 属性指代当且正在执行的函数

函数做用域的概念:在函数中声明的变量在整个函数体内都是可见的(包括在嵌套的函数中),在函数的外部是不可见的。不在任何函数内声明的变量是全局变量,在整个javascript程序中都是可见的

函数的执行依赖于变量做用域,这个做用域是函数定义是决定的,而不是函数调用是决定的

闭包

每次调用javascrip函数的时候,都会为之建立一个新的对象用来保存局部变量,把这个对象添加至做用域链中。当函数返回的时候,就从做用域链中将这个绑定变量的对象删除。若是不存在嵌套的函数,也没有其余引用指向这个绑定对象,它就会被看成垃圾回收掉。若是定义了嵌套的函数,每一个嵌套的函数都各自对应一个做用域链,而且这个做用域链指向一个变量绑定对象。但若是这些嵌套的函数对象在外部函数中保存下来,那么它们也会和所指向的变量绑定对象同样当作垃圾回收。可是若是这个函数定义了嵌套的函数,并将它做为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。它就不会被看成垃圾回收,而且它所指向的变量绑定对象也不会被看成垃圾回收。

做用:保存私有变量

var uniqueInteger=(function(){
  var counter=0;
  return function(){
    return counter++;
  };
  
}());

console.log(uniqueInteger());//0
console.log(uniqueInteger());//1
function constfuncs(){
  var funcs=[];
  for(var i=0;i<10;i++){
    
    funcs[i]=function(){
      return i;
    };
    
  }
  return funcs;
  
}
var funcs=constfuncs();
console.log(funcs[5]());//10

 函数的属性:

length 形参的数量

prototype每一个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,每一个函数都包含不一样的原型对象,当将函数用做构造函数的时候,新建立的对象会从原型对象上继承属性。

call apply看做某个对象的方法,经过调用方法的形式来间接调用函数,它们的第一个实参是要调用函数的母对象,它是调用上下文,在函数体内经过this来得到对它的引用,传入apply的参数数组能够是类数组对象也能够是真实数组。实际上,能够将当前函数的arguments数组直接传入apply来调用另外一个函数

bind 将函数绑定到某个对象

由ecma5 bind方法所返回的函数并不包含prototype属性(普通函数固有的prototype属性是没法删除的),而且将这些绑定的函数用做构造函数时所建立的对象从原始的未绑定的构造函数中继承继承prototype。一样,在使用instanceof运算符时,绑定构造函数和未绑定构造函数并没有两样。

if(!Function.prototype.bind){
  
  Function.prototype.bind=function(o){
    var self=this,boundArgs=arguments;
    return function(){
      var arg=[],i;
      for(i=1;i<boundArgs.length;i++){
        arg.push(boundArgs[i]);
      }
      for( i=0;i<arguments.length;i++){
        arg.push(arguments[i]);
      }
      return self.apply(o,arg);
    };
  }; 
}

Function 关于这个构造函数很是重要的一点,就是它所建立的函数并非使用词法做用域,想反,函数体代码的编译老是会在顶层函数执行

var scope="global";
function construction(){
  var scope="local";
  return new Function("return scope");
}

var p=construction();
console.log(p());//global

将Function构造函数被认为是在全局做用域中执行eval

判断是不是函数

function isFunction(x){

return Object.prototype.toString.call(x)==="[object Function]";

}

 

if((typeof Array.prototype.map)!="function"){
  Array.prototype.map=function(f){
    var results=[];
    var a=this;
    for(var i=0,len=a.length;i<len;i++){
      if(i in a){
        results[i]=f.call(null,a[i],i,a);
      }
    }
    
  };
}
if(typeof (Array.prototype.reduce)!="function"){
  Array.prototype.reduce=function(f,inital){
    var a=this;
    var i=0,len=a.length,accumulator;
    if(arguments.length>1){
      accumulator=inital;
    }
    else{
      if(len===0)
      {
        throw TypeError();
      }
      while(i<len){
        if(i in a){
          accumulator=a[i++];
          break;
        }
        
        else i++;
      }
      if(i==len){
        throw TypeError();
      }
      
      
    }
    while(i<len){
      if(i in a)
      {
 accumulator=f.call(undefined,accumulator,a[i],i,a); 
      }
      i++;
    }
  };
}


var sum=function(x,y){return x+y;};
var square=function(x){return x*x;};

var data=[1,1,3,5,5];
var mean=data.reduce(sum)/data.length;
var deviations=data.map(function(x){return x-mean;});
console.log(deviations);//[-2, -2, 0, 2, 2]

var stddev=Math.sqrt(deviations.map(square).reduce(sum)/(data.length-1));
console.log(stddev);[2]

高阶函数就是操做函数的函数

function not(f){
  return function(){
    console.log(this);
    var result=f.apply(this,arguments);
    return !result;
  };
}
var even=function(x){
  return x%2===0;
};
var odd=not(even);//判断是否为奇数
[1,1,3,5,5].every(odd);//true
function compose(f,g){
  return function(){
    
    return f.call(this,g.apply(this,arguments));
    
  };

}

var square=function(x){return x*x;};
var sum=function(x,y){return x+y;};

var squareofsum=compose(square,sum);
console.log(squareofsum(2,3));//25 先求和,再求平方
function compose(f,g){
  return function(){
    
    return f.call(this,g.apply(this,arguments));
    
  };

}
function array(a,n){
  return Array.prototype.slice.call(a,n||0);
}
function partialLeft(f){
  var args=arguments;
  return function(){
    var a=array(args,1);
    a=a.concat(array(arguments));
    return f.apply(this,a);
  };
}
function partialRight(f)
{
  var args=arguments;
  return function(){
    var a=array(arguments);
    a=a.concat(array(args,1));
    return f.apply(this,a);
  };
  
}
function partial(f){
  var args=arguments;
  
  return function(){
    var a=array(args,1);
    var i=0,j=0;
    for(;i<a.length;i++){
      
      if(a[i]===undefined){
        a[i]=arguments[j++];
      }
    }
    a=a.concat(array(arguments,j));
    
    return f.apply(this,a);
  };
  
}

var f=function(x,y,z){
  return x*(y-z);
};

console.log(partialLeft(f,2)(3,4));//-2 2*(3-4)
console.log(partialRight(f,2)(3,4));6 3*(4-2)
console.log(partial(f,undefined,2)(3,4));-6

 

 
function compose(f,g){
  return function(){
    
    return f.call(this,g.apply(this,arguments));
    
  };

}
function array(a,n){
  return Array.prototype.slice.call(a,n||0);
}
function partialLeft(f){
  var args=arguments;
  return function(){
    var a=array(args,1);
    a=a.concat(array(arguments));
    return f.apply(this,a);
  };
}
function partialRight(f)
{
  var args=arguments;
  return function(){
    var a=array(arguments);
    a=a.concat(array(args,1));
    return f.apply(this,a);
  };
  
}
function partial(f){
  var args=arguments;
  
  return function(){
    var a=array(args,1);
    var i=0,j=0;
    for(;i<a.length;i++){
      
      if(a[i]===undefined){
        a[i]=arguments[j++];
      }
    }
    a=a.concat(array(arguments,j));
    
    return f.apply(this,a);
  };
  
}

var f=function(x,y,z){
  return x*(y-z);
};
console.log(partialLeft(f,2)(3,4));
console.log(partialRight(f,2)(3,4));
console.log(partial(f,undefined,2)(3,4));
String.prototype.first=partial(String.prototype.charAt,0);

String.prototype.last=partial(String.prototype.substr,-1);
var text="javascript";
console.log(text.charAt(0));
console.log(text.first());

console.log(text.charAt(text.length-1));
console.log(text.last());

var not=partialLeft(compose,function(x){return !x;});

var even=function(x){return x%2===0;};
var odd=not(even);
var isNumber=not(isNaN);

console.log(odd(3));
console.log(isNumber("23123num"));
相关文章
相关标签/搜索