【JS】call()和apply()以及bind()方法

call和apply的说明
1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为方法的属性,那它们的使用就当然是针对方法的了,这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同。
2、语法:foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments) == this.foo(arg1, arg2, arg3);
3、相同点:两个方法产生的作用是完全一样的。
4、不同点:方法传递的参数不同。

function A(){
    this.flag = 'A';        //屏蔽这段,不影响代码
    this.tip = function(){
        console.log(this.flag);
    };
}
function B(){
    this.flag = 'B';        //函数A必须用这里的this.flag
}
var a = new A();
var b = new B();
a.tip()                    //A
a.tip.call(b);  //B
a.tip.apply(b); //B
// 从结果中可以看出callapply都可以让B对象调用A对象的tip方法,并且修改了this的当前作用对象为b

❤️看区别,上述是必须用function B里的this.flag,下面则要看情况,更灵活一点

function A(flag){
        // this.flag = flag;   //有这段,输出 bbbbb

    this.flag = 'A';            //有这段,输出 A;屏蔽这段,输出 B

    this.tip = function(){
        console.log(this.flag);
    };
}
function B(flag){
    this.flag = 'B';
    A.call(this, flag)
}
var a = new A();
var b = new B('bbbbb');
b.tip()
//输出 A, this.flag最后出现在哪里,最后就使用对应的值
function Add(a,b) {  
    console.log(a+b);  
}  
function Sub(a,b) {  
    console.log(a-b);  
}  
Add.call(Sub,3,1);   //4
// callapply都能修改当前作用对象Add为对象Sub,随即传递参数31,调用对象Add方法
function Product(name, price) {
    this.name = 'cake'
    this.price = 10
}
function Food(name, price) {
    // Product 函数内部的 this 变成了 Food  this
    // this.name = name  //会对应cheese
    this.name = 'nuddle'
    // ❤️对象food调用了对象product,并修改当前作用对象productthisfoodthis,随即对象product里的参数this.name  this.price的值会给food对象
    // 进而值'cake'会变成food.name的值
    Product.call(this, name, price) 
}
var product = new Product()
var food = new Food('cheese', 5)
// console.log(new Food('cheese', 5).name)
console.log(food.name)  //"cake"
function sum(num1, num2) { 
    return num1 + num2; 
    } 
console.log(sum.call(this, 10, 10)); //20 
console.log(sum.apply(this,[10,20])); //30 
var firstName = "diz"; 
var lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
  console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 
} 
HelloName.call(this); //Hello diz song glad to meet you!  
HelloName.call(myObject); //Hello my Object glad to meet you!

apply()和call()的真正用武之地是能够扩充函数赖以运行的作用域,如果我们想用传统的方法实现,请见下面的代码:
代码如下:

传统方法
var firstName = "diz"; 
var lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 
} 
HelloName(); //Hello diz song glad to meet you! 
myObject.HelloName = HelloName; 
myObject.HelloName(); //Hello my Object glad to meet you! 

传统方法:
要想让HelloName()函数的作用域在对象myObject上,我们需要动态创建myObject的HelloName属性,此属性作为指针指向HelloName()函数,这样,当我们调用myObject.HelloName()时,函数内部的this变量就指向myObjecct,也就可以调用该对象的内部其他公共属性了。

apply()方法

function sum(num1, num2) { 
return num1 + num2; 
} 
console.log(sum.call(this, 10, 10)); //20 
console.log(sum.apply(this,[10,20])); //30 
var array = ['a', 'b']
var elements = [0, 1, 2]
array.push.apply(array, elements)   // 结合push方法,["a", "b", 0, 1, 2]
// array.push.call(array, elements) // [ 'a', 'b', [ 0, 1, 2 ] ]
// array.push(elements)             // [ 'a', 'b', [ 0, 1, 2 ] ]
console.info(array); 
   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();    
    //通过callapply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。    
    //输入结果为"Cat"    
    animal.showName.call(cat,",");    
    //animal.showName.apply(cat,[]);  

bind()方法

bind()方法
color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
console.log(this.color); 
} 
var OSayColor = sayColor.bind(o); 
var RsayColor = sayColor;
RsayColor();  //red
OSayColor(); //blue

参考:
https://www.w3cschool.cn/xqw2e7/9m2x12y0.html

comments powered by Disqus