文章融会了《JavaScript高等程序设计》的学问,和这几天在segmentfault上的文章的学问点。属于整合类文章吧。
函数简介
函数声明和函数表达式
this和argument
闭包
函数简介
函数实际上是对象,所以函数名实际上是指向函数对象的指针,那末一个函数能够有多个名字。
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没有重载的观点,所以假如声清楚明了两个同名函数,则背面的函数会掩盖前面的函数。作为值得函数
函数名自身是变量,所以能够作为值来运用。不仅能够像通报参数一样把一个函数通报给另一个函数,而且能够将一个函数作为另一个函数的效果返回。
//把一个函数通报给另一个函数的例子
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;
}; //函数末端有分号,就像声明其他变量时一样。
不一定有函数名,所以有匿名函数表达式和定名函数表达式。不过,对函数定名后,一是在函数体内会表达得更清楚,二则是在调试的时刻要轻易许多。
区分:
函数声明能够在定义前挪用(函数声明提拔),函数表达式不能够(和其他表达式一样,运用前必需要赋值)。
函数声明只是让浏览器晓得有如许一个函数了,不会运转。浏览器碰到函数表达式会运转。
假如不做函数声明的话,平常就不愿望被反复挪用,即很大能够就当作马上实行函数运用。
假如函数体作为表达式的一部份,那它是函数表达式,否则为函数声明。
this和arguments
在函数内部有两个特别的对象: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变量的一个副本,就能够返回各自差别的值