ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

call和bind的原生实现

2021-06-01 21:34:09  阅读:112  来源: 互联网

标签:原生 function 调用 obj bind call let prototype


原生call的实现方法

原理:

当调用call时,call方法中的this就是调用体(也就是调用call的函数)

此时只需要将this赋值给传进来的对象,作为对象的方法进行调用,这样这个方法的this便会指向目标对象。当传进来的对象为null的时候,直接赋值为window

参数问题,,利用自带的arguments解决

代码

function person(a,b,c,d){
  console.log('name is '+this.name)
  console.log(a,b,c,d)
  return {
    a:11,
    b:12
  }
}
let jack = {
  name:'jack'
}
// 重写函数的call方法
Function.prototype.newCall=function (obj){
  // 当obj为null的时候指向window
  obj = obj || window
  // 获取除第一个以外的参数
  let arg = []
  for(let i = 1;i < arguments.length;i++){
    arg.push(arguments[i])
  }
  // 此处的this是调用体,在这里是person函数
  obj.b = this
  // 使用obj调用函数,使得被调用的函数的值指向obj
  // 保留函数原来的返回值
  const result = obj.b(...arg)
  delete obj.b
  return result
}
// 调用试一下
let result = person.newCall(jack,'father','mother','sister','brother')
console.log(result)

原生js实现bind

原理

调用bind时会返回一个函数,掉用函数时会改变this指向,获取this值,调用apply改变this指向

Function.prototype.newBind=function(obj){
  const arg1 = Array.prototype.slice.call(arguments,1)
  const that = this
  return  function(){
    const arg2 = Array.prototype.slice.call(arguments)
    return that.apply(obj,arg1.concat(arg2))
  }
}

比较麻烦的是这个new操作,会改变this指向

如下

function showName(a,b){
  console.log(this.name)
  console.log(a,b)
}
let obj = {
  name:'第一个'
}
let result = showName.bind(obj,'参数1','参数2')
result()	// "第一个" "参数1" "参数2"
let typeResult = new result() 	//undefined "参数1" "参数2"

故而需要进行如下修改

  • 首先返回的函数应该是一个具名函数,这样可以明确调用时的this指向并实现原型链的继承

  • 在调用时,需要使用instanceof判定当前的this是不是与返回的函数相关联

Function.prototype.newBind=function(obj){
  const arg1 = Array.prototype.slice.call(arguments,1)
  const that = this
  let back = function(){
    const arg2 = Array.prototype.slice.call(arguments)
     if(this instanceof back){
           return that.apply(this,arg1.concat(arg2))
     }
    return that.apply(obj,arg1.concat(arg2))
  }
  // 返回的值的原型对象需要与调用它的函数原型进行关联
  back.prototype = Object.create(this.prototype)
  // 上述语句与此处异曲同工
  // function o(){}
  // o.prototype = this.prototype
  // back.prototype = new o()
  return back
}

标签:原生,function,调用,obj,bind,call,let,prototype
来源: https://www.cnblogs.com/axu1997/p/14838962.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有