【基础知识】call,apply,bind

170 阅读1分钟

先来看个Demo

function Person(name){
    this.name = name;
    this.sex = "m";
    this.age = "20";
}
//定义实例方法introduceMe,otherMsg为该方法参数
Person.prototype.introduceMe = function(otherMsg="And I'm a student !") {
    return `
    Hello, everyBody ! 
    myName is ${this.name}; 
    mySex is ${this.sex}; 
    myAge is ${this.age} 
    ${otherMsg}
    `
}
let lilei = new Person("lilei");
console.log(lilei.introduceMe())  
/**
    Hello, everyBody ! 
    myName is lilei; 
    mySex is m; 
    myAge is 20 
    And I'm a student !
*/

function Fmail(name){
    this.name = name;
    this.sex = "f";
    this.age = "18";
    this.enjoy = "reading,playing...";
}
let hanxue = new Fmail();
//Fmail这个对象没有定义introduceMe方法,通过call可以调用
console.log(lilei.introduceMe.call(hanxue));
/**
    Hello, everyBody ! 
    myName is undefined; 
    mySex is f; 
    myAge is 18 
    And I'm a student !
*/

//hanxue这个Fmail的实例通过call调用introduceMe方法的同时,还可以传参
console.log(lilei.introduceMe.call(hanxue,"And I like reading !"));
/**
    Hello, everyBody ! 
    myName is undefined; 
    mySex is f; 
    myAge is 18 
    And I like reading !  --introduceMe传进的参数
*/
/**
    apply的写法:
    console.log(lilei.introduceMe.apply(hanxue,["And I like reading !"]));
    bind的写法:
    console.log(lilei.introduceMe.call(hanxue,"And I like reading !")());
*/

解析

  1. callapplybind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。
  2. callapplybind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;
  3. callapplybind 三者都可以利用后续参数传参;
  4. bind 是返回对应函数,便于稍后调用;applycall 则是立即调用 。
  5. bindcall接收参数序列(...args),apply接收数组参数(args)

方便理解:this即某对象实例(如demo中的hanxue),但该实例自身没有该方法,通过 方法.call(对象实例,参数)lilei.introduceMe.call(hanxue) hanxue就可以调用introduceMe方法了。

扩展

当this指向null或undefined时会自动指向全局对象(浏览器中的window对象)

    //所以某个函数的参数为序列时,可以这样用
    let arry = [1,3,4,2,5];
    Math.min.apply(null,array); //1
    //现在当然用 ... 扩展运算符更为方便了
    Math.min(...arry); //1