玩轉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

相關文章
相關標籤/搜索