函数内部属性
函数中有两个特殊的对象。
- arguments:它包含了所有的参数,重要的是它的一个叫做callee的属性,用于指向拥有这个参数的函数。好处是什么呢
实例:
function fa(num){
if(num<=1){
return 1;
}else{
return num*fa(num-1);
}
}
alert(fa(3));//6
这是一个普通的递归调用,但是却高度耦合,即严重依赖fa()。
但是使用了arguments.cellee(个人理解就是用这个可以代替函数名),就可以随意更换函数名了。
实例:
function fa(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
var fal = fa; //随意更改函数名
alert(fa(3));//6
alert(fal(3));//6
之所以能这样使用,是因为callee本身是一个指针。
- this:和java以及c的this含义大致一直,就是指当前所指的对象。
我们用实例来解释:
window.color = 'red';
var o = {color:'blue'};
function sayColor(){
alert(this.color);
}
sayColor(); //red
o.sayColor = sayColor; //没有()的函数名就是指针,这里把指针交给0.sayColor
o.sayColor(); //blue
sayColor作用与全局,而js中全局都是用window指代,所以直接调用sayColor的到的是red。
第二点,非常重要的一点,因为在js中,函数名本身其实就是一个指针,所以无论谁指向它都一样
- 函数对象的另一个属性caller,用于保存当前函数的引用(调用)。
下面是实例:
function outer(){
inner();
}
function inner(){
alert(inner.caller);
}
outer();
输出:
function outer(){
inner();
}
即inner的引用。
之前学习了arguments.callee这里也可以用,使得更为松散的耦合。
function outer(){
inner();
}
function inner(){
alert(arguments.callee.caller);
}
outer();
函数的属性和方法
函数既然是对象,就具有属性和方法。通用的属性是length和prototype。
length表示函数接收参数的个数:
function add(num1,num2){
return num1+num2;
}
alert(add.length); //2个参数
prototype在第六章
apply()和call()
apply实例:
function sum(num1,num2){
return num1+num2;
}
function callSum(num1,num2){
return sum.apply(this,arguments); //this是当前作用域范围(window,因为是在全局作用域中调用的)
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]);
}
alert(callSum(10,10)); //20
alert(callSum(10,10)); //20
call()唯一的不同是除了第一个this参数,其他传递参数必须一个个列举出来,实例:
function sum(num1,num2){
return num1+num2;
}
function callSum(num1,num2){
return sum.call(this,num1,num2);
}
alert(callSum(10,10)); //20
其实apply和call真正的作用是扩充函数的作用域。
实例:
window.color = 'red';
var o = {color:'blue'};
function sayColor(){
alert(this.color);
}
sayColor.call(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue
由上,本来sayColor是全局定义的函数,但是使用了call,在第三个调用中,使得结果为blue
bind()
bind用于创建实例函数,并且把this的值绑定在bind的函数上。
实例:
window.color = 'red';
var o = {color:'blue'};
function sayColor(){
alert(this.color);
}
var newSayColor = sayColor.bind(o);
newSayColor();//blue
基本包装类型
我们知道基本类型本来是不具备方法的,但是很高兴的是ecmascript提供了基本类型包装。
什么意思呢:当访问基本类型的时候,会创建一个基本类型的实例,在实力上调用方法,最后消除实例。这就使得基本类型和字符串一样了。
引用类型和基本类型的区别就是生存周期,引用类型会一直存在内存中,而基本类型包装则会在执行瞬间销毁