文章融合了《JavaScript高级程序设计》的知识,和这几天在segmentfault上的文章的知识点。属于整合类文章吧。segmentfault
函数简介数组
函数声明和函数表达式浏览器
this和argument闭包
闭包app
函数其实是对象,因此函数名其实是指向函数对象的指针,那么一个函数可能有多个名字。函数
function sum(num1,num2){ retrun num1+num2; } alert(sum(10,10)); //20 var anotherSum=sum; //将sum的值赋给了anotherSum,此时它们都指向同一个函数。 alert(anotherSum(10,10)); //20 sum=null; //将sum设置为null,使它与函数“断绝关系” alert(anotherSum(10,10)); //20 ,仍然能够正常调用。
没有重载
函数重载:函数重载是指在同一做用域内,能够有一组具备相同函数名,不一样参数列表的函数,这组函数被称为重载函数。js没有重载的概念,因此若是声明了两个同名函数,则后面的函数会覆盖前面的函数。this
做为值得函数
函数名自己是变量,因此能够做为值来使用。不只能够像传递参数同样把一个函数传递给另外一个函数,并且能够将一个函数做为另外一个函数的结果返回。设计
//把一个函数传递给另外一个函数的例子 function callFunction(someFunction,someArgument){ return someFuction(someArgument); } function add10(num){ return num+10; } var result=callFunction(add10,10); //要访问函数的指针而不执行函数的 话,要去掉函数名后的圆括号。 alert(result); //20
定义函数方法:指针
首先是函数声明: function functionName(){}
必须有函数名。
而后是函数表达式,好比:调试
var sum = function(num1,num2){ retrun num1+num2; }; //函数末尾有分号,就像声明其余变量时同样。
不必定有函数名,因此有匿名函数表达式和命名函数表达式。不过,对函数命名后,一是在函数体内会表达得更清晰,二则是在调试的时候要方便不少。
区别:
函数声明能够在定义前调用(函数声明提高),函数表达式不能够(和其余表达式同样,使用前必需要赋值)。
函数声明只是让浏览器知道有这样一个函数了,不会运行。浏览器遇到函数表达式会运行。
若是不作函数声明的话,通常就不但愿被重复调用,即很大可能就当作当即执行函数使用。
若是函数体做为表达式的一部分,那它是函数表达式,不然为函数声明。
在函数内部有两个特殊的对象:arguments和this。
arguments是一个类数组对象,包含传入函数的全部参数。主要做用就是保存函数参数。
arguments有一个callee属性,该属性是一个指针,指向拥有arguments对象的函数。
例子:
function factorial(num){ if(num<=1){ return 1; }else{ return num*factorial(num-1); } }
在函数factorial中调用了他自己,可是若是要是将函数赋值给别的变量,那就不能正常运行了。若是是下面的代码:
function factorial(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } }
这样,无论调用函数时使用什么名字,均可以保证正常完成递归调用。
this:
this引用的是函数据以执行的环境对象。
函数调用模式时,this指向window。
方法调用模式时,this指向方法所在对象。
wiondow.color="red"; var o={color:"blue"}; function sayColor(){ alert(this.color); } sayColor(); //"red" o.sayColor=sayColor; o.saColor(); //"blue"
构造函数模式时,this指向新生成的实例。
function Aaa(name){ this.name= name; this.getName=function(){ console.log(this.name) } } var a = new Aaa('kitty'); a.getName() // 'kitty' var b = new Aaa('bobo'); b.getName() // 'bobo'
apply/call调用模式时,this指向apply/call方法中的第一个参数。
var list1 = {name:'andy'} var list2 = {name:'peter'} function d(){ console.log(this.name) } d.call(list1) // 'andy' d.call(list2) // 'peter'
概念:是指有权访问另外一个函数做用域中变量的函数。
建立闭包方法:在一个函数内部建立另外一个函数。
特征:
能够访问外部函数的变量。
比较占内存。由于闭包会携带包含他的函数的做用域,在闭包被销毁后外部函数的活动变量才会被销毁。
(ps:关于活动变量知乎上这个问题的第二个答案写的很是很是好!)
闭包只能取得外部函数中任何变量的最后一个值。因此要注意闭包和循环的使用:
function foo(){ var result=new Array(); for (var i=0;i<10;i++){ result[i]=function(){ return i; }; } return result;
}
返回了一个函数数组,每一个函数都返回10。由于运行foo()函数的顺序是这样的:先运行foo()函数除了匿名函数以外的部分,完成后,再运行匿名函数。这时候for循环已经完成了,i变成了10。匿名函数引用foo()函数做用域内的活动变量i时,i已经等于10了,因此每一个函数返回的都是10。
改进:
function foo(){ var result=new Array(); for (var i=0;i<10;i++){ result[i]=function(num){ return function(){ return num; }; }(i); } return result; }
模仿块级做用域的方法。在调用外部的匿名函数时,传入参数i,变量i的值赋给num,在外部匿名函数内部的闭包,访问的是numresult数组的每一个函数都有本身num变量的一个副本,就能够返回各自不一样的值