js中的函数

   函数实际上是对象。每个函数都是Function类型的实例,而且与其他引用类型一样具有属性和方法。

由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。

 由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。换句话说,一个函数可能有多个名字。

function sum(num1,num2){

    return num1+num2 

}

alert(sum(10,10));  //20

var anotherSum = sum;

alert(another(10,10));  //20

sum =null;

alert(anotherSum(10,10));  //20

使用不带圆括号的函数名是访问函数指针,而非调用函数。此时,anotherSum和sum就都指向了同一个函数。

二,没有重载

function addSomeNumber(num){

      return num+100;

}

function addSomeNumber(num){

     return num+200;

}

var result = addSomeNumber(100);   //300

而结果是后面的函数覆盖了前面的函数。

5.5.2  函数声明与函数表达式

函数声明有一个函数声明提升的过程,而函数表达式没有。

 

5.5.3 作为值的函数

ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说不仅可以像传递参数一样把一个函数传递给另一个函数,

而且可以将一个函数作为另一个函数的结果返回。

function callSomeFunction(someFunction,someArgument){

   return somFunction(someArgument);


}

 5.5,4 函数内部属性

在函数内部,有两个特殊的对象:arguments和this。其中,arguments--虽然这个对象主要用途是保存函数参数,但是这个对象还有一个名叫callee的属性。

该属性是一个指针,指向拥有这个arguments对象的函数。实现递归:

 function factorial(num){
     if(num<=1){
         return 1;
     }else{
         return num*arguments.callee(num-1);
     }
 }
 console.log(factorial(5));

函数内部的另外一个特殊对象是this,this引用的是函数据以执行的环境对象

在网页全局作用域中调用函数时,this对象引用的就是window.

window.color ="red";
var o ={color:"blue"};

function sayColor(){
    alert(this.color);
}
sayColor();  //red

o.sayColor = sayColor();

o.sayColor()    //blue

上面这个函数sayColor()是在全局作用域中定义的,它引用了this对象。由于在调用函数之前,this的值并不确定,因此this可能会在代码执行的过程中引用不同的对象。

当在全局作用域中调用sayColor()时,this引用的是全局对象window,当把这个函数赋给对象o并调用o.sayColor()时,this引用的对象o.

重点:函数的名字仅仅是一个包含指针的变量而已,因此,即使在不同的环境下执行,全局sayColor()函数与o.sayColor()指向的仍然是同一个函数。

 

5.5.5  函数属性和方法

ECMAScript中的函数是对象,因此函数也有属性和方法,每个函数都包含两个属性:length和prototype.

function sayName(name){
    alert(name);
}
function sum(num1,num2){
    return num1+num2;
}
alert(sayName.length);  //1
alert(sum.length)     //2

 

prototype属性。

对于ECMAScript中的引用类型而言,prototype是保存他们所用实例方法的真正所在。

如toString() 和valueOf()等方法实际上都是保存在prototype名下,只不过是通过各自对象的实例访问。

每个函数都包含两个非继承而来的方法,apply()和call().这两个方法的用途都是在特定的作用域中调用函数。实际上等于设置函数体内this对象的值。

apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。

function sum(num1,num2){
    return num1+num2;
}

function applySum1(num1,num2){
    return sum.apply(this,arguments);  //传入arguments对象  这里的this是window对象
}

function applySum2(num1,num2){
    return sum.apply(this,[num1,num2]); //传入数组
}
alert(applySum1(10,10));
alert(applySum2(20,10));

 2,call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call(),第一个参数没变,变化的是其余参数都直接传递给函数。,也就是,在使用call()方法时,传递给函数的参数必须逐个列举出来。

function sum(num1,num2){
        return num1+num2;
    }

    function callSum(num1,num2){
        return sum.call(this,num1,num2);  //传入arguments对象
    }
    alert(callSum(10,10));  //20

事实上,apply()和call(),正真强大的地方是能够扩充函数赖以运行的作用域。

window.color="red";
var o ={color:"blue"};

function sayColor(){

    alert(this.color);
    
}

sayColor();   //red

sayColor.call(this);  //red   ----sayColor.call(this)和sayColor.call(window)则是显式地在全局作用域中调用函数的方式---结果都是red
sayColor.call(window); //red sayColr.call(o) //blue

使用call()或apply()来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。

bind()方法,这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

window.color = "red";
var o={color:"blue"};

function sayColor(){
    alert(this.color);
}
var objSayColor = sayColor.bind(o);

在这里sayColor()调用bind()并传入对象o,创建objsayColor()函数,objsayColor()函数的this值等于o,因此即使在全局作用域中调用这个函数,也会得到"blue"


 

posted @ 2017-10-23 17:18  千寻的天空之城  阅读(157)  评论(0编辑  收藏  举报