在js里,每个函数都是function类的实例。
一下三种效果几乎相同的方法,都可以用sum来引用函数。
function sum(var a,var b){return a+b};//函数声明法
var sum=function(var a,var b){return a+b};//函数表达式法
var sum=new Function("a","b","return a+b"};//构造函数法
但是第三种方法会导致解析两次代码,第一次解析常规代码,第二次解析构造函数里的字符串,从而影响性能。
因为函数名只是引用(存储地址的变量),所以一个函数可以有多个名字。而且这些引用互相独立。
比如:
var newsum=sum;
alert(newsum(10,10));
因此,函数没有重载,同名的函数会直接覆盖。
函数声明与函数表达式
在解析代码时,解析器已经通过一个名为函数声明提升的过程,率先读取并将函数声明添加到执行环境中,因此,即使调用函数的语句写在声明函数的语句之前,也可以正常执行。
alert(sum(10,10));//20
function sum(a,b){return a+b};
但是,假如函数不是声明而是表达式,就不能这样做。
alert(sum(10,10));//20
var sum = function (a,b){return a+b};
函数作为另一个函数的返回值
function createCompareFuntion(var proname){
return function(obj1,obj2){
var v1=obj1[proname];
var v2=obj2[proname];
if(v1<v2){
return -1;
}
else if(v1>v2){
return 1;
}
else{
return 0;}
}
}
var data=[{name:"aaa",age:12},{name:"bbb",age:15}];
data.sort(createCompareFuntion("age");
alert(data[0]).name);//aaa
为什么data.sort(compare)不需要传入参数呢,我的理解是由于参数不需要自己指定,它进行了封装,把compare函数传进sort函数,sort函数里面还有自带的参数,所以会自己调用compare函数
函数内部属性
arguments
一个类数组对象,除了保存函数所有的参数以外,还有一些重要的属性。
callee属性
该属性是一个指针,指向拥有这个arguments对象的函数。
常用于递归算法。函数自己调用自己时,如果函数没有名字,就可以用arguments.callee(参数)来调用自己。
caller属性
是函数自带的属性。指向调用当前函数的函数。
function outer(){
inner()
}
function inner(){
alert(arguments.callee.caller);//返回outer的源代码,在严格模式下报错
}
length属性
参数个数
prototype属性
函数内部方法
改变函数内部this值的三种函数自带的方法(apply,call,bind)
在全局环境里写的函数,里面的this指向的是window。
为了改变函数内部的this值,调用函数自带的apply方法
例如
obj1={
num1:1,
num2:2
};
window.num1=3;//this指向window
window.num2=4;
function sum(a,b){
return this.num1+this.num2+a+b;
}
function callSum1(a,b,c){
return sum.apply(obj1,arguments);//改变sum内部的this值为obj1,同时传入数组执行sum函数
}
callSum1(8,9,1);//20(多余的参数会被忽略)
call和apply的区别是传入的参数必须逐个列举出来,即sum.call(obj1,a,b,c);
这样做最大的好处是对象不需要与方法有任何耦合关系,方法不需要被放在对象里也可以获得对象的环境。
bind()
创建一个函数的实例,其this值会被绑定到参数上
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
}
var newfun=sayColor.bind(o)
newfun();//blue
三个会返回函数代码的方法:toLocaleString(),toString(),valueOf()