call、apply、bind

1、相同也不同

我们先从浅显的部分开始讲,

  • 这三个方法都可以改变this的指向,都可以进行传参,第一个参数都是修改this的指向
  • call() 和 apply() 改变this指向后会立即执行函数
  • bind() 改变this指向后不会立即执行
  • call() 和 apply() 区别在于参数

    · call() 第一个参数是修改的this指向,后续的参数都是传入该函数的值,他的传值只能一个个传

    · apply() 第一个参数是修改的this指向,第二个参数是一个数组,所有传入该函数的值都放到该数组中

 

javaScript权威指南上的解释是:

  call() 、apply()可以看作是某个对象的方法,

  通过调用方法的形式来间接调用函数。

  bind() 就是将某个函数绑定到某个对象上。

 


 

 

2、照常举🌰

var boy = {
      name : "李雷",
      gender : "男",
      age : 17,
      say : function() {
             alert(this.name + " , " + this.gender + " ,今年" + this.age);                                
      }
}
var  girl = {
      name : "韩梅梅",
      gender : "女",
      age : 16
}
boy.say();

此时弹出的内容是:

  李雷,男,今年17

 

那么如果我们想输出girl这个对象的数据怎么办,

换种说法就是,

在只改变这个代码最后一句话的情况下怎么让girl对象拥有say这个方法?

//对于call
boy.say.call(girl);

//对于apply
boy.say.apply(girl);

//对于bind
boy.say.bind(girl)();

由此可以看出:

  call() 和 apply() 改变this指向后会立即执行函数,

  bind方法返回的仍然是一个函数需要调用才会执行

 

此时我们把🌰换成需要传递参数的:

var boy = {
      name : "李雷",
      gender : "男",
      age : 17,
      say : function(mes1,mes2) {
             alert(this.name + " , " + mes1 + mes2);                                
      }
}
var  girl = {
      name : "韩梅梅",
      gender : "女",
      age : 16
}
boy.say("喜欢","韩梅梅");


//此时输出:李雷,喜欢韩梅梅


//call
boy.say.call(girl,"也喜欢","自己")

//apply
boy.say.apply(girl,["也喜欢","自己"])

//bind
boy.say.bind(girl,"也喜欢","自己")()

 


 

 

3、如何自己写一个call方法呢?

思路:call方法的思路是改变this的指向,让新的对象可以执行该函数,

   那么思路是否可以变为给新的对象添加一个函数,

     执行后再删除呢?

//自定义一个myCall方法挂载到Function通过prototype实现公共方法

Function.prototype.myCall = function (context) {

//context是obj2,因为只获取了第一个参数
//与call方法一样,context中第一个为新的this的指向
//剩下的部分为传入的参数

//此处是如果没传this指向的话就指向window

  var context = context || window

//此处的this指向调用myCall的函数,就是你定义的初始对象的函数
//此处对应的this就是obj1.fn

  context.fn = this

//获取除了this指向其余的参数

  var args = [...arguments].slice(1)

//指向函数并把参数传进去

  var result = context.fn(...args)

//删除该方法

  delete context.fn

  return result

}


var obj1 = {
    name:'name1',
    fn:function(mes){
        console.log(this.name+mes)
    }
}

var obj2 = {
    name:"name2"
}

obj1.fn.myCall(obj2,"111")

//输出name2111

 


 

 

4、如何自己写一个apply方法呢?

//整体与call没什么太大的区别
//那我们就主要看看区别
//区别就在于是否需要传参
//因为他的参数全都在数组里

Function.prototype.myApply = function (context) {
  var context = context || window
  context.fn = this

  var result
  // 需要判断是否存储第二个参数
  // 如果存在,就将第二个参数展开
  if (arguments[1]) {
    result = context.fn(...arguments[1])
  } else {
    result = context.fn()
  }

  delete context.fn

  return result
}

 


 

 

5、如何自己写一个bind方法呢?

Function.prototype.myBind = function (context) {
  var _this = this
  var args = [...arguments].slice(1)
  // 返回一个函数
  return function () {
    return _this.apply(context, args.concat(...arguments))
  }
}

 

 

以上。

posted on 2018-12-15 21:34  薛小白  阅读(436)  评论(0编辑  收藏  举报