您的位置:首页 > Web前端 > JavaScript

javascript 函数

2016-03-13 15:25 162 查看
1 函数声明语句会被提前到外部脚本或外部函数作用域顶部,这种方式定的函数,可以在它被定义之前出现的代码所调用。

以表达式定义的函数,必须把它复制给一个变量,变量声明提前了,但是变量赋值不会提前,所以表达式方式定义的函数在定义之前无法调用。

//计算阶乘的递归函数
function factorial(x){
if (x<=1) return 1;
return x*factorial(x-1);
}

//函数用来求传入参数的平方
var square=function(x){return x*x;}


2函数调用 作为函数 作为方法 作为构造函数 通过call()和apply()方法间接调用

(1) 函数调用

var probability=factorial(5)/factorial(13);


(2) 方法调用 o.m(x,y) 属性表达式由两部分组成,一个对象(o)和属性名称(m)对象o成为调用的上下文,函数体可以使用关键字this引用该对象

var calculator={
operand1:1,
operand2:1,
add:function() {
//tihs指代当前对象
this.result=this.operand1+this.operand2;
}
};
calculator.add();
calculator.result  //2


嵌套函数作为方法调用,其this值指向调用它的对象。

如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)

var o={                     //对象o
m:function(){           //对象中的方法m()
var self=this;
console.log(this===o);//输出true  this就是这个对象o
f();                    //调用辅助函数f()

function f(){           //定义一个嵌套函数f()
console.log(this===o);//false this值是全局对象或者undefined
console.log(self===o);//true self指向外部函数的this值
}
}
}
o.m();//调用对象o的方法m()


(3) 构造函数调用 函数或者方法调用之前带有关键字new

var o=new Object();
var o=new Object;//凡是没有形参的构造函数调用都可以省略圆括号


构造函数调用创建一个新的空对象,这个对象继承自构造函数的prototype属性。

(4) 间接调用

call()使用它自有的实参列表作为函数的实参。apply()方法要求以数组的形式传入参数。

3 函数的实参和形参

当调用函数传入的实参比形参的个数少,剩下的形参都是undefined

//将对象o中可枚举属性名追加到数组a中,并返回这个数组a
//如果省略a,则会创建一个新数组并返回这个数组
function getPropertyNames(o,a){
if (a===undefined) a=[];//如果未定义,则使用新数组
for (var property in o) a.push(property);
return a;
}

//这个函数调用可以传入1个或者2个实参
var a=getPropertyNames(o);//将o的属性存储到一个新数组中
getPropertyNames(p,a);//将p的属性追加到数组a中


当调用函数传入的实参比形参的个数多时:

定义函数f时,它的参数只有一个x.调用函数时传入两个参数,第一个参数可以通过参数名x来获得,也可以通过arguments[0]来得到。第二个参数只能通过arguments[1]来得到。

//接收任意数量的实参,并返回实参最大值
function max(){
var max=Number.NEGATIVE_INFINITY;
for (var i=0;i<argumengs.length;i++){
if (arguments[i]>max)  max=arguments[i];
return max;
}
}
var largest=max(1,20,22,0,3,5,88,4,585);//585


arguments[0] x指代同一个值,修改其中一个会影响到另一个

//形参和实参的对应关系
function f(x){
console.log(x);//输出实参的初始值
arguments[0]=null;//修改实参数组的元素同样会修改x的值
console.log(x);//输出null
}


严格模式下函数无法使用arguments作为形参名或者局部变量名,也不能给arguments赋值

callee和caller属性:callee属性指代当前正在执行的函数 caller指调用当前执行函数的函数

4对象属性用做实参

//数组元素的复制
function easycopy(args){
arraycopy(args.form,
args.form_start||0,//设置可默认值
args.to,
args.to_start||0,args.length);
}
//调用
var a=[1,2,3,4],b=[];
easycopy({from:a,to:b,length:4});


5作为值的函数

function square(x) {return x*x;}
var s=square;

var o={square:function(x) {return x*x ;}};//将函数赋值给对象的属性
vay y=o.square(16);//y=256

var a=[function(x) {return x*x;},20];//数组直接量
a[0](a[1]);//400


6闭包

嵌套函数时可以访问作用域内的变量的,而且可以访问外部函数中定义的counter变量

var uinqueInteger(function(){  //定义函数并立即调用
var counter=0;
return function(){return counter++;};
})

function counter(){
var n=0;
return{
count:function(){return n++;},
reset:function(){n=0;}
};
}
var c=counter(),d=counter();//创建两个计数器
c,count()//0
d.count()//0
c.reset()
c.count()//0 重置了c
d.count()//1


每次调用counter()都会创建一个新的作用域链和一个新的私有变量。因此,如果调用counter()两次,就会得到两个计数器对象,而且彼此包含不同的私有变量,调用其中一个计数器对象的count()或reset()不会影响到另外一个对象。

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


解释:上述代码创建了10个闭包,并存储到一个数组中。这些闭包在同一个函数中定义,因此它们共享变量i.当constfuncs()返回时,变量i的值是10,所有的闭包共享这个值,因此数组中的函数返回值都是同一个值。

函数调用都包含一个this值,如果闭包在外部函数里是无法访问this的,除非外部函数将this转存为一个变量 var self-this;//将this保存在一个变量中

由于闭包具有自己绑定的arguments,因此闭包无法直接访问外部函数的参数数组,除非外部函数将参数数组保存到另外一个变量中 var outerArguments=arguments;

7

//blind 函数绑定至一个对象
var sum=function (x,y){return x+y};
//创建一个类似sum的新函数,但this的值绑定到null,第一个参数绑定到1
var succ=sum.bind(null,1);
succ(2) //3  x绑定到1  传入2作为实参y

function f(y,z){ return this.x+y+z};
var g=f.bind({x:1},2); //绑定this 和y
g(3)  //6  this.x绑定到1,y绑定到2,z绑定到3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: