1.Function类型
在ECMAScript中,函数实际上是对象,每个函数都是Function
类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
函数内部属性
函数内部,有两个特殊的对象:arguments
和this
。
arguments
之前的学习中已经对arguments
进行了总结,继续深入学习一下相关知识:
Arguments的作用
- (1)重载
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。 Javascript
并没有重载函数的功能,但是Arguments对象能够模拟重载。这样能够解决参数传递过程中的不定参问题。
function test(...nums){
var sum = 0;
for(var i=0;i
sum += nums[i];
}
console.log(sum);
}
- (2)递归(不建议使用)
function factorial(n){
if(n == 1){
return 1;
}else{
n * arguments.callee(n-1);
}
}
如果参数过大,频繁调用,会显著的影响现代 JavaScript
引擎的性能,每次调用自己,不仅抵消了内联函数带来的性能提升,而且破坏了封装。
callee
callee
是arguments
对象的一个属性、用来指向当前执行的函数,它的用法之前已经学习总结过,在严格模式下并不支持arguments.callee
的使用,因此建议不使用。但是可以使用命名函数表达式来达成相同的结果:
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});
以上代码创建了一个名为f()
的命名函数表达式,然后将它赋值给变量factorial
。即便把函数赋值给了另一个变量,函数的名字f依然有效。这种方式在严格模式和非严格模式下都行得通。
2 函数属性和方法
ES中的函数是对象,也有属性和方法。每个函数都包含两个属性:length
和prototype
。length
表示函数希望接收的命名参数的个数,也就是我们通常设置的形参的个数。
prototype
属性保存了引用类型的所有实例方法,每个函数都包含两个非继承而来的方法:apply()
和call()
.这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this
对象的值。
this
this
是一个引用指针,指向的是函数执行的环境对象,不同的环境this
指向的值不同。
apply()
方法接收两个参数,一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array
的实例,也可以是Arguments
对象。
如示例:
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments); // 传入arguments对象
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]); // 传入数组
}
callSum1(10,10); //20
callSum2(10,10); //20
在上面这个例子中,callSum1()
在执行sum()
函数时传入了this
作为this
值,因为是在全局作用域中调用的,因此传入的就是window
对象和arguments
对象。而callSum2()
同样也调用了sum()
函数,但它传入的则是this和一个参数数组。这两个函数都会正常执行并返回正确的结果。
call()
方法与apply()
方法的作用相同,区别仅在与接收参数的方式不同。对于call()
方法而言,第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()
方法时,传递给函数的参数必须逐个列举出来。
使用call()
,apply()
的真正目的在与扩充函数赖以运行的作用域。
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.color
的求值会转换成对window.color
的求值。
而sayColor.call(this)
和sayColor.call(window)
是两种显示地在全局作用域中调用函数的方式,结果都会显示red
。但是当运行sayColor.call(o)
时,函数的执行环境就不一样了,此时函数体内的this
对象指向o,显示blue
。
使用call()
,apply()
来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。
ES5
中还定义了bind()
方法,会创建一个函数的实例,其this值会被绑定到传给bind()
函数的值。
window.color="red";
var o={color:'blue'};
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); // blue
sayColor()
调用bind
并传入对象o,创建了objectSayColor()
函数,objectSayColor
函数的this
等于o。
3.总结
函数的名字仅仅是一个包含指针的变量而已,在严格模式下未指定环境对象而调用函数,this
值不会指向window
,除非明确的把函数添加到某个对象或者调用apply()
或call()
,否则this
都会指向undefined
。
改变this
指向真正强大的地方在于能够扩充函数运行的作用域。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!