js中函数的 this、arguments 、caller,call(),apply(),bind()

在函数内部有两个特殊的对象,arguments 和 this,还有一个函数对象的属性caller。

arguments对象

arguments是一个类似数组的对象,包含着传入函数的所有参数。

function doAdd(){
    if(arguments.length == 1){
        return arguments[0] + 10;
    }else if(arguments.length == 2){
        return arguments[0] + arguments[1];
    }
}
console.log(doAdd(11));  // 21
console.log(doAdd(11,20)); // 31

 

arguments对象还有一个属性callee,该属性是一个指针,指向拥有这个arguments对象的函数。

function factorial(num){

    if(num <=1){
        return 1;
    } else {
        return num*arguments.callee(num - 1);
    }

}
// 消除代码和函数名的耦合。

 

在严格模式 ("use strict")下,访问 arguments.callee 会出错。

在严格模式下也能实现递归:

var factorial = (function f(num){

    if(num <=1){
        return 1;
    } else {
        return num*f(num - 1);
    }
});
console.log(factorial(4)); // 24

 

this对象

this引用的是函数的执行环境对象。在函数调用之前this对象的值是不确定的,在网页浏览器的全局作用域中调用函数时,this对象引用的是window:

 

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

function sayColor(){
    alert( this.color);
}
sayColor();  // red,  在全局作用域中调用函数,this引用的是window对象

o.sayColor = sayColor; 
o.sayColor();   // blue, 引用对象o

 

caller属性

caller属性指向调用该函数的函数,如果是在全局作用域中调用当前函数,它的值为null:

function outer(){
    inner();
}
function inner(){
    console.log(inner.caller);
// console.log(arguments.callee.caller); } outer();
// 打印outer函数的源代码 inner(); //打印null

call()和apply()

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

apply()有两个参数,第一个是运行时函数的作用域(执行环境)对象,第二个是参数对象,可以是arguments对象,或者是数组

call()函数的第一个参数也是作用域对象,其余参数是传递给函数的参数,需要逐个列出来

apply()和call()最常用的场景是改变函数运行的作用域。这样对象就可以不需要和方法有任何耦合的关系

var color = "red";
var o = {"color":"blue"};
function sum(num1,num2){
    console.log(this.color);
    return num1+num2;
}
function callSum1(num1,num2){
    return sum.apply(this, arguments);
}
function callSum2(num1,num2){
    return sum.apply(this, [num1,num2]);
}

function callSum3(num1,num2){
    return sum.call(this, num1,num2);
}

o.callSum1 = callSum1;
o.callSum2 = callSum2;


console.log(callSum1(10,10));  // red 20
console.log(callSum2(10,10));  // red 20
console.log(callSum1.apply(o,[10,10]));  // blue 20
console.log(callSum3.call(o,10,10));  // blue 20,直接改变作用域
console.log(o.callSum1(5,10));  // blue 15 
console.log(o.callSum2(5,10));  // blue 15

 bind()

bind()函数会创建一个函数实例,新的函数的this值为被绑定为传给bind()函数的值

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

function sayColor(){
    console.log(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); // blue, 即使在全局中调用,this值仍为对象o

 

posted @ 2019-02-19 11:18  zhanglw  阅读(211)  评论(0)    收藏  举报