call和apply

 

callapplybind方法学习总结

1 window对象

        window对象是js中的顶层对象,所有全局变量和全局函数都被绑定在了window对象身上:

        var a = 10;               //全局变量

function abc(){           //全局函数

    console.log("Young");

}

console.log(window);      //此时在window对象内已经出现了a属性和abc函数

 

window对象作为一个全局对象,一般情况下在使用的时候是可以省略的,也就是不写都可以拿到a的值和执行abc函数。

 

2 this关键字,也就是所谓的执行上下文

        this关键字存在于函数中,表示是一个指向,或者说是一个系统“变量”,值并不是固定的。

this的指向为:谁调用当前this所在的函数,this就指向谁。也就是说,当前调用函数的那个对象自身就是this,就是当前的执行上下文。

 

3         执行上下文(this)的改变

(1)       改变this指向的目的:

在代码中,当一个对象A具有一个方法fn,另一个对象B没有方法,但是需要用到同样功能的fn方法时,可以通过改变A对象中函数fn的执行上下文(this)来实现调用,达到节约代码空间,不产生冗余函数的目的。

如下代码1-1(字面量创建对象):

 

 
  文本框: var A = {
    name: "AAA",
    fn: function(skill){
    this.skill = skill;
      console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
var B = {
    name: "BBB"
}
A.fn("sing");          //my name is AAA, my skills are sing
B.fn("dance");         //Uncaught TypeError: B.fn is not a function;

 

 

 

 

 

 

 

 

 

 

 

 

再如下代码1-2构造函数创建对象:

 

 
  文本框: function ProA(name, skill){
    this.name = name;
    this.skill = skill;
    this.fn = function(){
      console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
function ProB(name, skill){   }

var A = new ProA("AAA","sing");
A.fn();             //AAA

var B = new ProB("BBB","dance");
B.fn();             //Uncaught TypeError: B.fn is not a function;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

使用call来修改执行上下文this

基本语法结构:call(thisObj,arg1,arg2,arg3,……)

 

call方法接收一个或一个以上的参数,当接收一个参数时,第一个参数表示要改变的原函数的执行上下文(this);接收多个参数时,第二个参数及后面所有参数用来替换原函数的参数。

 

使用call方法将代码1-1改成如下代码2-1方式,即可让对象B具有对象Afn方法:

 

 
  文本框: var A = {
    name: "AAA",
    fn: function(skill){
        this.skill = skill;
        console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
var B = {
    name: "BBB"
}
A.fn("sing");                 //my name is AAA, my skills are sing
//此处改动产生的效果为:
//在执行A对象的函数fn时,通过call将函数fn的执行上下文(this)暂时修改为对象B,
//此时fn中的this指向对象B,同时修改原函数fn的参数为“dance”,
//call方法自动执行改变之后的原函数
A.fn.call(B,"dance");         //my name is BBB, my skills are dance

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

将代码1-2使用call方法改成如下代码2-2方式,构造函数方式创建对象写法:

 

 
  文本框: function ProA(name, skill){
    this.name = name;
    this.skill = skill;
    this.fn = function(){
        console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
function ProB(name, skill){
    //此处改动产生的效果为:
    //在ProB内,通过apply,执行,并改动ProA中的执行上下文(this),
    //及修改ProA的参数为ProB所接收的参数
    //那么在new调用ProB时,相当于调用了被修改了执行上下文和参数之后的ProA
    ProA.call(this, name, skill)
}
var A = new ProA("AAA","sing");
A.fn();          //my name is AAA, my skills are sing
var B = new ProB("BBB","dance");
B.fn();          //my name is BBB, my skills are dance

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

使用apply改变this

语法:apply(thisObj,argArr)

 

apply方法接受一个或两个参数,当接收一个参数时,第一个参数表示要改变的原函数的执行上下文(this);接收两个参数时,第二个参数必须是数组(或伪数组),用于替换原函数中arguments保存的参数,

 

将代码1-1使用apply改为以下代码3-1,即可让对象B具有对象Afn方法:

 

 
  文本框: var A = {
    name: "AAA",
    fn: function(skill){
    this.skill = skill;
        console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
var B = {
    name: "BBB"
}
A.fn("sing");                  //my name is AAA, my skills are sing
//此处改动产生的效果为:
//在执行A对象的函数fn时,通过apply将函数fn的执行上下文(this)暂时修改为对象B,
//此时fn中的this指向对象B,同时修改原函数fn的参数为“dance”(注意“dance”参数必须是数组的形式),
//apply方法自动执行改变之后的原函数
A.fn.apply(B,["dance"]);       //my name is BBB, my skills are dance

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

使用apply方法将代码1-2改为以下代码3-2

 

 
  文本框: function ProA(name, skill){
    this.name = name;
    this.skill = skill;
    this.fn = function(){
        console.log("my name is " + this.name +", my skills are " + this.skill);
    }
}
function ProB(name, skill){
    //此处改动产生的效果为:
    //在ProB内,通过apply,执行,并改动ProA中的执行上下文(this),
    //及修改ProA的参数为ProB所接收的参数(注意:此时的参数必须是一个数组的格式)
    //那么在new调用ProB时,相当于调用了被修改了执行上下文和参数之后的ProA
    ProA.apply(this, [name, skill])
    //参数也可以写成arguments的形式,arguments属于伪数组,但是也可以被apply所接收处理,如:
    //ProA.apply(this, arguments)
}
var A = new ProA("AAA","sing");
A.fn();        //my name is AAA, my skills are sing
var B = new ProB("BBB","dance");
B.fn();        //my name is BBB, my skills are dance

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

callapply的主要区别就是call可以接受一个或以上的参数,当接受多个参数时,从第二个参数开始,后面所有的参数都会改变原函数的参数;apply只能接受一个或两个参数,当接受两个参数时,第二个参数必须是一个数组或类数组,数组中的数据,会改变原函数arguments中的参数。

callapply的第一个参数,都是用来改变原函数的this指向。

 

 

 

posted @ 2019-11-12 16:27  未见青山  阅读(209)  评论(0)    收藏  举报