ECMAScript中,函数就是对象,每个函数都是function类型的实例,并且具有属性和方法。为了理解这一概念,可从函数的定义方式入手。
function sum(num1, num2){
return num1 + num2;
}
var sum = function(num1, num2){
return num1 + num2;
}
var sum = new Function("num1","num2","return num1 + num2"); //不推荐使用
以上的三种方式都可以定义函数,前两种方式是常用的定义方式,第三种不推荐使用。但从第三种定义方式可看出,函数名就是一个引用类型的指针变量,函数就是一个对象。
既然函数名只是函数对象的指针,所以,一个函数可以有多个同时指向它的指针,即多个函数名。
function sum(num1, num2){
return num1 + num2;
}
alert(sum(10,10)); //20
var anotherSum = sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20
1. 没有重载
ECMAScript中不存在函数重载,只会覆盖
var addSomeNumber = function(num){
return num + 100;
};
addSomeNumber = function(num){
return num + 200;
};
var result = addSomeNumber(100); //300
既然函数名是指针,在重新赋值后自然重新指向新的内存空间
2. 函数声明和函数表达式
在之前所说的函数的三种定义方式中,以function开头的定义方式会被解析器最先初始化,以var开头的定义方式则不会
alert(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}
// 可以正常运行
alert(sum(10,10));
var sum = function(num1, num2){
return num1 + num2;
}
// 运行期间产生报错
3. 作为值的函数
因为函数名本身就是变量,所以也可以作为值来使用,可以作为参数传递给另一个函数,也可以作为另一个函数的返回结果。
function callSomeFunction(someFunction, someArgument){
return someFunction(someArgument);
}
function add10(num){
return num + 10;
}
var result1 = callSomeFunction(add10,10);
alert(result1); //20
function getGreeting(name){
return "hello, " + name;
}
var result2 = callSomeFunction(getGreeting, "word");
alert(result2); //"hello, word"
以下代码根据函数可作为另一个函数的返回结果的特性,灵活地实现了对数组的自定义排序
function createComparisonFunction(propertyName){
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if(value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0;
}
}
}
var data = [{name:"zhangsan",age:28}, {name:"lisi", age:29}];
data.sort(createComparisonFunction("name"));
alert(data[0].name); //lisi
data.sort(createComparisonFunction("age"));
alert(data[0].name); //zhangsan
4. 内部属性arguments
arguments是函数对象中的一个属性,是一个类数组对象,包含着传入函数中的所有参数。
arguments有一个callee方法,可以调用拥有其arguments的函数,常用于做递归
function factorial(num){
if(num <= 1){
return 1;
}else {
return num * arguments.callee(num - 1);
}
//实现了求num的阶乘
}
alert(factorial(5)); //120
ECMAScript 5 规范了另一个函数对象的属性:caller,除了Opera早期版本,其他的浏览器都支持。这个属性中保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值为null
function outer(){
inner();
}
function inner(){
alert(arguments.callee.caller);
}
outer(); //outer函数的代码
inner(); //null
5. 内部属性this
this也是函数对象中的一个属性,引用的是函数的执行环境对象,设置类的属性和方法时需要通过this关来引用
window.color = "red";
function Circle(color){
this.color = color;
}
function sayColor(){
alert(this.color);
}
sayColor(); //"red"
var o = new Circle("blue");
o.sayColor = sayColor;
o.sayColor(); //"blue";
6. 函数属性prototype和length
函数的prototype属性是指向其原型的引用,JavaScript通过prototype属性实现了许多面向对象的功能
length是函数希望接收的参数个数
function sayName(name){
alert(name);
}
function sum(num1,num2){
return num1 + num2;
}
function sayHi(){
alert("hi");
}
alert(sayName.length); //1
alert(sum.length); //2
alert(sayHi.length); //0
7. 函数方法call、apply和bind
call()方法和apply()方法的作用相同,区别在于接收的参数不同
function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this,num1,num2);
}
function applySum(num1, num2){
return sum.apply(this,[num1,num2]);
}
alert(callSum(10,10)); //20
alert(applySum(20,20)); //40
更重要的是,call()方法和apply()方法可以扩充函数的作用域,与prototype组合使用可以实现继承
window.color = "red";
var o = {color: "blue"};
function sayColor(){
alert(this.color);
}
sayColor();
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
ECMAScript 5 定义了一个方法:bind(),这个方法会创建一个函数实例,其this值会被绑定到穿个bind()函数的值
支持的浏览器:IE9+、Firefox 4+、Safari 5.1+、Opera 12+和Chrome
window.color = "red";
var o = {color: "blue"};
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
参考文献: JavaScript高级程序设计(第3版)