函数就是一段被封装的代码,定义一次可以被执行无数次。在js中,函数也可以作为一类数据,作为值来赋给变量,对象属性,或者数组元素。
1.定义对象
一共有三种方法:
使用function语句,使用Function()构造函数和定义函数直接量
声明函数
function funName([agrs]){
statements
}
function 结构是静态的,只有调用的时候才能被执行,var和function语句都是变量声明语句,都是在预编译期间被解析的。
构造函数
var funName = new Function(p1,p2,...,body)
其中p1,p2是参数,最后一项是方法内部结构体语句
例如
var f = new Function("a","b","return a+b")
缺点:代码可读性差,并且Function是在执行期间被编译的,执行效率非常低
函数直接量(匿名函数)
例如:
function(a,b){
return a+b
}
同样我们可以把上面的直接量赋值给一个变量 f,即
var f = function(a,b){
return a+b
}
函数作用域
使用Function构造器创建的函数有全局作用域,而function和函数直接量定义的函数都有局部作用域
例子
var n =1 ;
function f(){
var n =2;
function e(){
return n;
}
return e;
}
alert(f()()); //执行完返回的是2
var n =1 ;
function f(){
var n =2;
var e = new Function("return n ;")
return e;
}
alert(f()()); //执行完返回的是1
使用函数
函数有一个入口,一个出口,入口为参数,出口为return 返回值作为出口
其中 如果想反悔多个值,需要把返回值设计成数组。
在嵌套函数中,js遵循的是从内到外的就近调用函数,但是不会从外到内调用函数,这样就避免了函数中调用同名函数可能引发额冲突
例如
function f(){ //顶级函数f
return 1;
}
function o(){ //函数作用域
return o(); //调用内部函数o
function o(){ //函数内部作用域
return f(); //嵌套函数内部函数f
function f(){
return 3;
}
}
}
alert(f()) //1
alert(o()) //3
函数作用域
在函数内声明的参数,变量,私有函数 对外是不可见的。
对象可以通过.的方式来访问内部成员,但是在函数体外,无法通过.来调用内部包含的成员。
函数可以通过return 向外界开放内部成员
使用参数
参数分为实参和形参
形参就是函数声明的参数变量,实参就是实际传递的参数值
例如
function f(a,b){ //a,b就是形参
return a+b
}
var x=1,y=2
alert(f(x,y)) //x,y就是实参
通过 函数名.length 可以获得形参的格式 上例中 f.length 可以得到2
js并没有要求形参和实参的个数相同。 但是 当形参个数大于实参个数的时候,多余的形参会是undefined。而当实参个数大于形参个数的时候,多余的实参将会被忽略。
当形参和函数体内定义的私有变量重名时,私有变量的优先级要大于形参
使用arguments对象
arguments对象是一个伪类数组,可以通过下角标的反射光hi获取函数的实参值,但是没有Array的原型方法
例如
function f(){
alert(arguments.length) //返回3
}
f(3,4,5)
注:arguments对象只能在函数体内使用
通过修改arguments的length值,可以达到改变函数实参个数的目的。
callee回调函数
arguments有一个callee属性,它引用当前arguments对象所属的函数。使用该属性可以在函数体内调用函数自己。在匿名函数中,callee属性比较有用。 利用它可以进行函数迭代
也就是说 arguments.length指的是实参的个数,而arguments.callee.length指的是形参的个数
arguments.callee.length 等价于 函数名.length
使用函数对象
自定义属性
作为对象,用户可以通过点语法为函数定义静态属性和方法
function.property
function.method
函数属性可以在函数体内定义,也可以在函数体外定义
function f(){
f.x =1;
}
f.y=2
注:函数外定义的属性可以随时访问,而函数内定义的属性只可以在函数被调用完之后,可以访问
函数的方法与嵌套的函数不同,嵌套的函数只能在内部可见,而函数的方法可以在外部被调用,
function f(){
f.x = function(x){
return x
}
}
f.y = function(y){
return y*y
}
alert(f.y(3))
f(); //如果不进行f()调用 下面代码会报错
alert(f.x(4))
使用call() 和 apply()
他们是Function的原型方法,能够将特定函数当作一个方法绑定到指定对象上去
function f(x,y){
return x+y;
}
function o(a,b){
return a*b;
}
alert(f.call(o,3,4))
上面的方法 f是一个简单的函数,而o是一个构造函数对象,通过call()方法 就把f这个函数绑定到了o身上,变为了o的一个方法
就相当于 o.m =f ; alert(o.m(3,4));delete o.m
个人理解, 就是把一个函数 送给了一个对象当作对象里面的方法了。
call()和apply()是一样的 只不过call()需要把参数一个个列出来,而apply()是以数组形式传递的。
使用call() 和apply() 可以复制调用函数的内部变量给当前的函数体
使用bind()
用来把函数绑定到指定对象上,也就是说,对于给定的函数,创建具有与原始函数相同的主体的绑定函数,在绑定函数中 this对象将会被解析成传入的对象。绑定函数具有指定的初始参数。
function.bind(thisArg[arg1,arg2])
bind 方法会返回与function相同的函数,thisArg对象和初始参数除外
var originalObject ={
minimum:50,
maximum:100,
checkNumberRange:function(value){
if(typeof value !='number')
return false;
else
return value>=this.minimum && value<=this.maximum
}
}
var result = originalObject.checkNumberRange(10);
document.write(result);
var range = {minimum:10,maximum:20}
var boundObjectWithRange = originalObject.checkNumberRange.bind(range)
var result = boundObjectWithRange(10);
document.write(result);
首先直接调用originalObject.checkNumberRange(10) 其中this指的是originalObject中定义的。 接着把originalObject.checkNumberRange方法绑定到了range对象上,并且返回了一个相同的函数叫boundObkectwithRange 说明this指向的是range里面的属性。