玩转js之——call方法的模拟实现

call方法的模拟实现

初步思考

const person = {
   name:"小明"
 }
 function sayName() {
   console.log(this.name)
 }

 sayName.call(person)

 //result: 小明

上面的代码有两个步骤javascript

  1. call 改变了this 的指向,指向变为 person
  2. sayName 函数执行了
//猜想
 const person = {
   name:"小明",
   sayName() {
      console.log(this.name)
   }
 }
 //此时的this绝壁指向person,可是要实现call 咱们很差给每一个对象都加属性,but 加了在删除好像也没啥

第一步尝试版

  1. 给person 对象添加fn方法
  2. sayName函数执行
  3. 删除person中的fn方法
Function.prototype.myCall = function (obj) {
   console.log(obj) // { name: '小明' }
   console.log(this) //[Function: sayName]
 }
 //看到上面的打印结果是否是心中已经有了答案

按照三个步骤实现java

Function.prototype.myCall = function (obj) {
  obj.fn = this
  obj.fn()
  delete obj.fn
}
sayName.myCall(person) //result: 小明

第二步加入参数版

咱们知道call函数的参数除了能够改变this指向的对象,还能够传入指定的其余参数 好比下面:数组

const person = {
  name: "小明"
}

function sayName(age, phone) {
  console.log(age)
  console.log(phone)
  console.log(this.name)
}

sayName.call(person, 12, 12345) // 12 12345 小明

可是参数的数量不可控 因而咱们能够这么写 tips:1.arguments 是一个类数组对象 不是一个真的数组 2.eval 是个很特殊的方法 网上褒贬不一函数

Function.prototype.myCall = function (obj) {
  obj.fn = this

  let _arguments = deepCopy(arguments)
  delete _arguments[0]
  let args = []
  for (let key in _arguments) {
    args.push(_arguments[key])
  }
  let  args_str= args.join()
  // obj.fn(args_str) 这种作法显然不行 至关于只传进了一个字符串

  eval('obj.fn(' + args_str +')'); //经过eval处理

  delete obj.fn
}

sayName.myCall(person, 12, 12345) //12 12345 小明

写到这里是否是很开心(^▽^),咱们已经完成90%啦优化

第三步终极进化优化版

1.call(obj) 万一obj为null怎么办?this

let name = "上帝"

function sayName() {
  console.log(this.name)
}

console.log(sayName.call(null)) //上帝

2.call 最终应该有返回spa

function getU(age, phone) {
  return{
    age,
    phone
  }
}
console.log(getU.call(person)) //{ age: undefined, phone: undefined }

解决起来很简单,代码以下prototype

Function.prototype.myCall = function (obj) {
  obj = obj || window

   ...
   ...
   ...

  const result = eval('obj.fn(' + args_str +')');

  ...

  return result
}

console.log("result",getU.myCall(person, 12, 12345)) //result { age: 12, phone: 12345 }

到此为止咱们的call 就写完啦,(^▽^)code

相关文章
相关标签/搜索