目录
一、函数声明与函数表达式
函数声明与函数表达式区别:解析器在解析代码时对函数声明和函数表达式会有“区别对待”,解析器会率先读取函数声明使其在执行任何代码时可用(此过程为函数声明提升);而函数表达式需要等到解析器执行到所在位置才会被解释执行,如下:
alert(add(1,2)); // 3
function add(num1,num2){
return num1+num2;
}
alert(add(1,2)); // add is not a function
var add = function(num1,num2){
return num1+num2;
}
二、函数的内部属性
函数内部有两个比较重要的属性:arguments和this。
arguments是用来存储函数的参数,它类似一个数组对象,但并不是一个数组,可以使用数组下标的方式访问函数的参数,如arguments[0],arguments还有个callee属性,它指向了拥有这个arguments对象的函数,可在递归函数中使用这个属性,如下。
(function test(){
alert(arguments instanceof Array); // false
alert(typeof arguments); // object
})() // 证明arguments不是一个数组
function sum(num){
if(num > 0){
return num+sum(num-1);
}else{
return 0;
}
}
// 以下方式降低了紧密耦合的现象
function sum(num){
if(num > 0){
return num+arguments.callee(num-1);
}else{
return 0;
}
}
this指向了函数的当前执行环境,关于this的使用见如下。
var color = "red";
function sayColor(){
alert(this.color);
}
var obj = {
color:"blue",
sayColor:sayColor
}
sayColor(); // red,此时this指向的是window,所以弹出的是window.color
obj.sayColor(); // blue,此时this指向的是obj,所以弹出的是obj.color
ECMAScripts 5规范了函数对象的另一个属性:calller,他保存调用当前函数的函数引用,如果在全局作用域下调用函数,它的值为null。
function test2(){
alert(test2.caller);
}
function test3(){
test2();
}
test2(); // null,全局作用域下调用
test3(); // 在test3中调用了test2,返回test3的引用
三、函数属性和方法
每个函数都有两个属性:length和prototype。
length属性表示函数所期望接收参数的个数,不是arguments.length,如下所示。
// arguments.length返回的是传递参数的个数,而add.length返回的则是函数所期望的被传递参数的个数
function add(num1,num2){
alert(arguments.length);
return num1+num2?num2:0;
}
add(1,2); // 2
add(1); // 1
add.length;// 2
prototype属性下保存着所有的实例方法,例如toString()、value()等方法都保存在prototype属性下。可使用prototype属性来拓展JS内置的对象(不建议)。继承就是靠这个属性实现的。
每个函数还包含两个非继承来的方法:apply()、call()。两个方法的作用都是一样的,都是改变函数运行的作用域。apply()方法接收两个参数,第一个参数是函数所要运行的作用域,第二个参数可以是数组,也可以是arguments。call()方法的第一个参数是函数所要运行的作用域,而后面的参数是不确定的,取决于被改变函数所接收的参数,也就是说从第二个参数开始,后面参数是传递给函数的参数的遍历,如下。
function add(num1,num2){
return num1+num2;
}
function addCopy1(num1,num2){
return add.apply(this,arguments);
}
function addCopy2(num1,num2){
return add.apply(this,[num1,num2]);
}
function addCopy3(num1,num2){
return add.call(this,num1,num2);
}
add(1,2); // 3
addCopy1(1,2); // 3
addCopy2(1,2); // 3
addCopy3(1,2); // 3
ECMAScript 5中还定义了一个bind()方法。该方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值,例如:
var obj = {
color:"red"
}
var color = "blue"
function sayColor(){
alert(this.color);
}
sayColor(); // blue
sayColor.bind(obj)(); // red