JS里面的call, apply以及bind

Posted 笨鸟居士的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS里面的call, apply以及bind相关的知识,希望对你有一定的参考价值。

参考了这篇文章:http://www.tuicool.com/articles/EVF3Eb

给几个例子

function add(a,b)  
{  
    alert(a+b);  
}  
function sub(a,b)  
{  
    alert(a-b);  
}  
add.call(sub,3,1);

这个运行是什么呢?答案:

4. 运行的是add.

因为call是运行的调用者。将第一个参数作为this参数来使用。

 

再来一个例子

function Animal(){    
    this.name = "Animal";    
    this.showName = function(){    
        console.log(this.name);    
    }    
}    
function Cat(){    
    this.name = "Cat";    
}    
var animal = new Animal();    
var cat = new Cat();

animal.showName.call(cat,",");   
或者
animal.showName.apply(cat,[]); 

答案是:

Cat。 因为this换做了Cat。

 

另外,继承时候用来调用父类的构造函数

function Animal(name){      
    this.name = name;      
    this.showName = function(){      
        console.log(this.name);      
    }      
}      
function Cat(name){    
    Animal.call(this, name);    
}      
var cat = new Cat("Black Cat");     
cat.showName();

调用完父类之后,cat也有了showName的方法。

 

下面这两种调用基本等价:

myfunc.call(func,"var"," fun");
myfunc.apply(func,["var"," fun"]);

 

关于bind:作用:改变了上下文的this

bind与call不同点有两个:

①bind的返回值是函数。

//使用bind是 返回改变上下文this后的函数

//使用call是 改变上下文this并执行函数

②后面的参数的使用也有区别

function f(a,b,c){
    console.log(a,b,c);
}

var f_Extend = f.bind(null,"extend_A")
f("A","B","C")  //这里会输出--> A B C

f_Extend("A","B","C")  //这里会输出--> extend_A A B

f_Extend("B","C")  //这里会输出--> extend_A B C

f.call(null,"extend_A") //这里会输出--> extend_A undefined undefined

call 是 把第二个及以后的参数作为f方法的实参传进去

而bind 虽说也是获取第二个及以后的参数用于之后方法的执行,但是f_Extend中传入的实参则是在bind中传入参数的基础上往后排的。

所以,以下两个是等价的:

var f_Extend = f.bind(null,"extend_A")

//↓↓↓

var f_Extend = function(b,c){
    return f.call(null,"extend_A",b,c);
}

有一个应用场景:

例如现在有一个方法 根据不同的文件类型进行相应的处理,通过bind 就可以创建出简化版的处理方法

function FileDealFunc(type,url,callback){
    if(type=="txt"){...}
    else if(type=="xml"){...}
    .....
}

var TxtDealFunc = FileDealFunc.bind(this,"txt");
//这样使用的时候更方便一些

FileDealFunc("txt",XXURL,func);  //原来

TxtDealFunc(XXURL,func); //现在

对于旧的版本,可以用以下方式做兼容处理(EcmaScript5中扩展了叫bind的方法(IE6,7,8不支持))

if (!Function.prototype.bind) {
    Function.prototype.bind = function(obj) {
        var _self = this
            ,args = arguments;
        return function() {
            _self.apply(obj, Array.prototype.slice.call(args, 1));
        }
    }
}

不过上面的函数,好像只接受了一个参数。

 

以上是关于JS里面的call, apply以及bind的主要内容,如果未能解决你的问题,请参考以下文章

转 - JS 中 call 和 apply 以及 bind 的区别

JS call,apply, bind区别

手撸JS call,apply,bind

手撸JS call,apply,bind

js call()apply()bind()的区别和使用

JS中call,apply,bind方法的总结