javaScript深入之call、apply、bind的实现

call的实现

 call的作用有两点:1.改变this 2.让函数执行

实现call之前,简单梳理一下:

1.call的第一个参数可以为null,undefined,当为null和undefined的时候,函数中的this指向window

2.函数的返回值可以顺利返回

3.当第一个参数传入基本类型的数据时 会被包装成对象  

Function.prototype.myCall = function (thisArgs, ...args) {
  var _this = this;
  // 如果是简单类型就包装一下 如果是null或者undefined 就返回window
  thisArgs = thisArgs == null ? window : Object(thisArgs) 
  var fn = Symbol('fn');//避免属性被覆盖
  thisArgs[fn]= _this;
  var res = thisArgs[fn](...args); // 采用默认绑定 让调用hycall的函数中this指向thisArgs
  delete thisArgs[fn]; 
  return res
}

到这里就完成了call的原理实现,这里再给大家出一道题,测试一下自己对call的理解

我们的函数执行可以用aaa.call()来执行,也可以直接aaa()来执行

function aaa(){
  console.log('aaa')
}
aaa()//aaa
aaa.call()//aaa

下面的例子中fn中的this是{name: 'yql'}, "hello"和world是传给fn的参数 

function fn(a, b) {
  console.log(this); // { name: 'yql' }
  console.log(a, b); // hello world
}
fn.call({ name: "yql" }, "hello", "world")

最后我们再看一下多次call的例子:

function fn(){
    console.log(this)
}
function fn1(a, b){
 console.log('100')
 console.log(a, b)
}
fn.call.call.call.call(fn1, 'hello', 'world') ?

有了上面两个小例子作为基础,多次call也方便理解了,首先不管写几个call 都是call方法本身去调了一下call(fn1),最后可以简写成call.call(fn1), 也就是call方法中的this是fn1,最后相当于执行fn1.call(),也就是fn1执行,所以最后打印出100,"world", "undefined" 

apply的实现

 apply的作用有两点:1.改变this 2.让函数执行

 apply实现之前,简单梳理一下:

1.当apply的第二个参数可以不传

2.apply第二个参数必须是一个数组

3.其余跟call一样

Function.prototype.myApply = function (thisArgs, args) {
  var _this = this;
  // 如果是简单类型就包装一下 如果是null或者是undefined 就返回window
  thisArgs = thisArgs == null ? window : Object(thisArgs)  
  var fn = Symbol('fn');//避免属性被覆盖
  thisArgs[fn] = _this;
  args = args || [] //没有传参数的时候 args是undefined 不能用展开运算符 
  var res = thisArgs[fn](...args); // 默认绑定 函数中this指向thisArgs
  delete thisArgs[fn];
  return res
}

bind的实现

bind的作用:1.返回一个新函数2.改变this,3.需要手动调用执行

bind的实现之前,简单梳理一下:

1.调bind会返回一个函数

2.函数的参数可以分开传,也可以一次性传

3.其余跟call一样

Function.prototype.myBind = function (thisArgs, ...argsArray) {
  var _this = this;
  thisArgs = thisArgs == null ? window : Object(thisArgs)
  return function (...args) {
    var fn = Symbol('fn');
    thisArgs[fn]= _this;
    args = args || [] //没有传参数的时候 args是undefined 不能用展开运算符
    var res = thisArgs[fn](...argsArray, ...args);  // 参数拼接
    delete thisArgs[fn];
    return res
  }
}

function sum1(num1, num2, num3, num4) {
  return num1 + num2 + num3 + num4
}
// 使用方式 参数可以分开传 也可以一次性传完
var fn = sum1.bind('abc', 10, 20)
var result = fn(30, 40)

var foo = {

    value: 1,

    bar: function() {

        console.log(this.value)

    }

};

foo.bar(); // 1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值