在JS中,函数都是对象,都是Function类型的实例,有自己的属性和方法。因此函数名也像其他引用类型一样,是一个指向函数对象的指针。
定义函数有三种方式:
1、函数声明(有函数声明提升)
function add(num1,num2){
return num1+num2;
}
2、函数表达式(无函数声明提升)
var add=function(num1,num2){
return num1+num2;
};
3、Function构造函数(不推荐)
var add=new Function("num1","num2","return num1+num2;");
最后一个参数始终被认为是函数体,前面的所有参数均被认为是参数。该方法会导致两次解析代码:1、常规解析ECMAScript代码 2、解析传入构造函数的字符串,影响性能。
因为函数名仅仅是指向函数对象的指针,所以可以被当成参数或者返回值。
例1: 将add作为参数传入op函数
function op(func,arg){
return func(arg);
}
function add(num){
return num+10;
}
console.log(op(add,20)); //返回30
例2: 从一个函数返回另一个函数
//实现根据对象的某个属性对一个对象数组进行排序
function compare(arg){
return function(obj1,obj2){
var val1=obj1[arg];
var val2=obj2[arg];
if(val1<val2){return -1;} //升序
else if(val1>val2){return -2;}
else{ return 0; }
}
}
var objArray=[{name:"master",age:18},{name:"Tom",age:16}];
objArray.sort(compare(age)); //根据年龄进行比较
console.log(objArray[0].name); //输出"Tom"
函数内部属性:
函数内部有两个特殊的对象:arguments 和 this
1、arguments对象是一个类数组对象,里面保存着函数的参数,该对象还有一个callee属性(严格模式下访问该属性会报错),是一个指针,指向拥有该arguments的函数。
比如:一个递归函数,被删掉函数名后......
function dg(num){
if(num<=1){ return 1; }
else{
return num*dg(num-1);
}
}
var other=dg;
dg=null;
other(10); //报错,因为函数内部调用了dg,可是dg已不存在
//所以,应该将函数内部的dg换为arguments.callee(num-1);
2、this引用的是函数执行的环境对象。
3、caller属性,指向调用当前函数的函数的引用
function outer(){
inner();
}
function inner(){
alert(inner.caller);
}
outer(); //alert 弹出 outer的源代码
inner.caller == arguments.callee.caller;
函数属性和方法:
1、length 表示函数期望接受的命名参数的个数。
2、prototype 属性 是不可枚举属性,用for-in无法发现。
3、apply( ) 和 call( ) 这两个是非继承而来的函数。在特定的作用域中调用函数,实际上是设置函数体内this对象的值。
function sum(num1,num2){
return num1+num2;
}
function op(num1,num2){
return sum.apply(this,arguments);
}
op(10,20); //返回30
sum.apply 修改了sum函数体内的this对象的值。call用法类似,只是call需要一个一个传参,apply要传一个参数数组。
这两个函数真正强大的地方是“扩充函数赖以运行的作用域”
var color="red";
var o={ color:"blue" }
function sayColor(){
console.log(this.color);
}
sayColor.call(this); //显示red
sayColor.call(window); //显示red
sayColor.call(o); //显示blue,在这里sayColor的函数作用域就被调到了o对象中。
使用call和apply来扩充作用域的好处就是对象不需要与任何方法有任何的耦合关系。
4、bind( ) 方法,该方法会创建一个 调用它的函数 的实例,其this值指向参入的参数。
var color="red";
var o={ color:"blue" }
function sayColor(){
console.log(this.color);
}
var other=sayColor.bind(o);
other(); // blue