函数
函数
函数是这样的一段JavaScript代码,它只被定义一次,但可能被执行或调用任意次。
函数的定义会包括一个称为形参(parameter)的标识符列表,这些参数在函数体中像局部变量一样工作。
函数的实参指的是调用函数的时候传入的参数
如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法。当通过这个对象来调用函数时,这个对象就是此次调用的上下文(context),也就是该函数的this的值
定义函数:
Function 函数名(参数){函数体}
函数可以定义后立刻调用:
Var tensquared=(function(x){return x*x;}(10)); //将参数10传递给给刚定义的函数,得到的结果赋值给tensquared
嵌套函数
Function hypotenuse(a,b){
Function square(x){return x*x;}
Return Math.sqrt(square(a)+square(b));
}
函数调用
4种方式调用JavaScript函数:
1、 作为函数
2、 作为方法
3、 作为构造函数
4、 通过它们的call()和apply()方法间接调用
方法调用
一个方法无非是个保存在一个对象的属性里面的JavaScript函数。如果有一个函数f和一个对象o,则可以用下面的代码给o定义一个名为m()的方法
O.m=f;给O对象定义了方法m(),调用它时就像这样:O.m();
Var calculator={
Operand1:1,
Operand2:1,
Add: function(){ this.result=this.Operand1+this.Operand2;}
};
Calculator.add();
Calculator.result ==>2
对象的属性和方法不只是使用.调用,也可以使用中括号调用
O[“m”](x,y); //o.m(x,y)的另一种写法
构造函数调用
没有形参的构造函数调用都可以省略圆括号,下面两个是等价的。
Var o=new Object(); var o=new Object;
间接调用
JavaScript中的函数也是兑现,和其他的JavaScript对象没什么两样,函数对象也可以包含方法。其中两个方法call()和apply()可以用来间接地调用函数。两个方法都允许显示指定调用所需的this值,也就是说,任何函数可以作为任何对象的方法来调用,哪怕这个函数不是那个对象的方法。Call()方法使用它自有的实参列表作为函数的实参,apply()方法要求以数组的形式传入参数。
函数的实参和形参
可选形参,当调用函数的时候传入的实参比传入的形参个数少的时候,剩下的形参将都设置为undefined。因此在调用函数时形参是否可选以及是否可以省略应当保持较好的适应性。为了做到这一点,应当给省略的参数赋一个合理的默认值。
function getPropertyName(o,/* optional */ a){
if(a==undefined) a=[];
for(var property in o)
a.push(property);
return a;
}
这样这个函数可以传入1个或者两个实参
如果在第一行代码中不使用if语句,可以使用||运算符,这是一种习惯写法 a=a||[];
注意: 当使用这种可选实参来实现函数时,需要将可选实参放在实参列表的最后。同时注意在函数定义中使用注释/*optional*/强调形参是可选的
可变长的实参列表:实参对象
当调用函数时候传入的实参个数超过函数定义时的形参个数时,没有办法直接获得未命名值的引用。实参对象可以解决这个问题。
函数体内,标识符arguments是指向实参对象的引用
比如一个函数f,它的形参只有一个x如果在调用这个函数的时候传入两个实参,第一个参数可以通过x获得,也可以通过arguments[0]获得,第二个参数只能通过arguments[1]获得。、
Function f(x,y,z){
If(arguments.llength!=3){
Throw new Error(“function f called with”+arguments.length+”arguments,but it excepts 3 arguments.);
}
}
当然,在大多数情况下,多出的实参不会影响,省略的实参是undefined,多出的实参将会自动省略
callee和caller属性
在严格模式中,对这两个属性的读写操作都会产生一个类型错误。
在非严格模式下,callee属性只带当前正在执行的函数。Caller是非标准的,但是大多数浏览器都实现了这个属性,它指代当前正在执行的函数的函数。
使用这两个属性可以实现匿名函数的递归调用:
Var factorial=function(x){
If(x<=1) return 1;
Return x* arguments.callee(x-1);
}
将对象属性作为实参
作为值的函数
当函数作为对象的属性调用,就称为方法
函数甚至不需要带名字,当把它们赋值给数组元素。
函数可以这样用:
Function mymodule(){//方法体代码}
Mymodule();//调用方法
==>相当于
(function(){//方法体代码}());//创建匿名函数表达式并且调用
闭包
函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特征在计算机科学中称为闭包。
函数属性、方法和构造函数
Length属性: arguments.length表示传入函数的实参的个数。函数本身的length属性是只读属性,代表定义时的形参个数
Prototype属性
每一个函数都包含一个prototype属性,这个属性是指向一个对象的引用,这个对象称做“原型对象(prototype object)“。
apply和call方法
Call()方法和apply()方法可以看作是某个对象的方法,通过调用方法的形式;来间接调用函数。
Call()和apply()的第一个实参是要调用的函数的母对象,它是调用上下文,在函数体内通过this获取对它的引用。
O的对象调用f函数
f.call(o);或者f.apply(o);
call和apply可以有多个参数,第一个参数都是代表调用方法的对象
在call中,后面的参数依次是调用方法的实参
Apply中只有两个参数,第二个蚕食是传入方法的参数的数组对象,可以是类数组对象也可以是真实数组
function f(a,b,c){ return a+b+c; } var o={},p={}; alert(f.call(o,1,2,3)); alert(f.apply(p,[1,2,3]));
Bind()方法
将函数绑定至某个对象。当在函数f()上调用bind()方法并穿额U一个对象o作为参数,这个方法将返回一个新的函数。(以函数调用的方式)调用新的函数会把原始的函数f()当作o的方法来调用。传入新函数的任何实参都将传入原始函数。
Bind()的参数可以有多个,第一个表示的是绑定的对象,后面的是绑定方法的部分形参,从第一个开始,可以不全,不全的话在调用中补全。
// JavaScript Document function f(y){return this.x+y;} var o={x:1}; /*var g=f.bind(o); alert(g(2));*/ function bind(f,o){//重写find方法 if(f.bind) return f.bind(o); else return function(){return f.apply(o,arguments); }; } /*var g=f.bind(o); alert(g(3));*/ var sum=function(x,y){ return x+y; } var succ=sum.bind(null,1); /*alert(succ(2));*/ function f1(y,z){ return this.x+y+z; } var g=f1.bind({x:1},2); //绑定this和y alert(g(3));
toString()方法。
大多数返回的是函数的完整源码。内置函数往往返回的是类似[native code]的字符串
Function()构造函数
不管是通过构造函数定义语句还是函数直接量表达式,函数的定义都要使用function关键字。但是函数还可以通过function()构造函数来定义,比如:
Var f=new Function(“x”,”y”,”return x*y;”);等价于
Var f=function(x,y){return x*y};
可调用对象callable object是一个对象,可以在函数调用表达式中调用这个对象。所有的函数都是可调用的,但并非所有的可调用的对象都是函数。例如:
Window.alert()和Document.getElementById()使用了可调用的宿主对象,而不是内助函数对象。RegExp对象也是可调用对象
判断一个对象是否是真正的函数对象(并且具有函数方法):
Function isFunction(x){
Return Object.prototype.toString.call(X)===”[object Function]”;
}
函数式编程
JavaScript并非函数式编程语言,但在JavaScript中可以像操控对象一样操控函数。
数组的reduce(a,b)方法a为回调函数,b为初始值、map(a)方法 a为针对数组值的操作方法
高阶函数:操作函数的函数,接受一个或多个函数作为参数,并返回一个新的函数