我们大家都知道,一个函数它有属性和方法,每个函数都包含两个属性:length和prototype。
length属性
length属性表示函数希望接收的命名参数的个数。
举个例子
function sayName(name){
alert(name);
}
function sum(sum1,sum2){
return num1 + num2;
}
function sayHi(){
alert("hi");
}
alert(sayName.length); //1
alert(sum.length); //2
alert(sayHi.length); //0
上述代码中,我定义了三个函数,三个函数所带参数的个数不同,因此length属性值也各不相同。
prototype
prototype属性是保存它们所有实例方法的真正所在,也就是说,toString()和valueOf()等方法实际上都保存在prototype之下,只不过是通过各自对象的实例来进行访问的。
每个函数都包含两个非继承而来的方法:apply()和call()。
相同之处:都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
区别 两个方法仅在于接收函数的方式不同。
apply()
1.apply()方法接收两个参数:一个是其中运行函数的作用域,另一个是参数数组。
2.参数可以是Array的实例,也可以是arguments对象。
function sum(num1,num2){
return num1 + num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments);
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]);
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
在这个例子中
callSum1()在执行sum()函数时传入this作为this值(因为是在全局作用域中作用的,所以传入是window对象)和arguments对象。
callSum2()同时也调用了sum()函数,但是它传入的是this和一个参数数组。
这两个函数都会正常执行并返回正确结果。
call()
function sum(num1,num2){
return num1 + num2;
}
function callSum(num1,num2){
return sum.call(this,num1,num2); //参数逐个列举
}
alert(callSum(10,10)); //20
在使用call()方法时,callSum()必须明确出入每一个参数。
事实上,传递参数并不是这两个方法真正的用武之地;它们强大的地方在于能够扩充函数赖以运行的作用域。
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
sayColor()是一个全局变量。在全局作用域中调用它时,会显示“red”,因为此时的this就是window。
但是当运行sayColor.call(o)时,函数的执行环境发生了变化,此时的this指向了o,于是结果变成了“blue”。
好处 使用这两个方法扩充作用域最大的好处在于,对象不需要与方法有任何耦合关系。
网友评论