整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          javascript核心知識(七):手寫代碼實現ca

          javascript核心知識(七):手寫代碼實現call函數

          unction foo() {

          console.log(this)

          }

          foo()//window

          var arr1=[]

          foo.call(arr1))//[]

          // call原理

          Function.prototype.myCall=function (target) { //形參就相當于 var target=undefined

          /*

          實現原理:把目標函數foo綁定在目標對象target上(本來函數的this指向window,但是想要讓this指向我們指定的對象,所以有下面這些操作)

          1. 獲取目標對象

          2. 獲取目標函數 foo,并把目標函數foo綁定到目標對象上

          3. 執行目標函數并返回

          */

          //如果傳參則使用Object()包裹一下,有可能不是一個對象,若沒有傳參默認為window

          target=target ? Object(target) : window

          //將targetFunction綁定到target上,targetFunction是定義的臨時屬性

          target.targetFunction=this

          //獲取傳入的除了target以外剩余的參數

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

          let result=target.targetFunction(...args)

          //刪除臨時屬性

          delete target.targetFunction

          return result

          }

          var arr1=[]

          foo.myCall(arr1))//arr1 []

          注意:target.targetFunction=this這行代碼的意思就是把foo.call(arr1) 中的foo函數掛載到arr1上。當執行foo.myCall() 時, myCall里的 this 指向調用者foo,所以這里的this就是foo函數。

          javascript調用一個函數有兩種方法,

          (1)直接使用函數名以及對應的參數

          (2)使用call進行調用

          代碼

          定義一個函數

          /**
           * 兩數相加得到結果
           * @param {double} x 
           * @param {double} y 
           * @returns 相加結果
           */
          function CalNum(x,y){
              return x+y;
          }
          

          正常調用方法

              // 正常調用函數
              var x=1, y=2;
              var ret=CalNum(x,y);
              console.log("正常調用的結果是:" + ret);

          結果是:

          正常調用結果是:3

          使用call進行方法調用

              //使用call調用當前的函數
              var obj={
                  name:"x"
              }
              var ret2=CalNum.call(obj,x,y);
              console.log("采用call調用的結果是:" + ret2);

          注意:使用call調用的時候。funcion中的this將變成obj而不是function本身的this.

          或者使用空對象來進行

          var ret2=CalNum.call({},x,y);

          最終的結果是

          采用call調用的結果是:3

          核心

          使用call的核心是是改變function的this指向問題,不再是指向本身,而是指向傳入的對象。

          文分享自華為云社區《關于 JavaScript 中 call 方法的實現,附帶詳細解析!-云社區-華為云》,作者:CoderBin。

          本文將全面的,詳細解析call方法的實現原理,并手寫出自己的call方法,相信看完本文的小伙伴都能從中有所收獲。

          創作不易,你們的點贊收藏留言就是我最大的動力

          如果文中有不對、疑惑的地方,歡迎各位小伙伴們在評論區留言指正

          call 方法的實現

          1. 函數作用

          調用函數,可傳入參數,改變this指向

          2. 總體步驟

          1. 邊界判斷(this,context)
          2. 將調用的函數設置為對象(傳入的context)的方法(改變this指向)
          3. 調用函數,得到返回值,并返回

          3. 詳細步驟

          1. 邊界判斷

          • 判斷當前 this 是否為一個函數,否則返回錯誤消息
          • 判斷傳入的 context 參數是否存在,存在則使用 Object() 轉換為對象賦給 context,否則將 window 賦值給 context

          2. 將調用的函數設置為對象(傳入的context)的方法(改變this指向)
          3. 調用函數,得到返回值,并返回

          • 調用函數,得到結果
          • 刪除 context 身上的 fn 函數
          • 返回結果

          4. 代碼實現

          /**
           * !實現 binCall() 方法
           * @param {*} context 綁定的對象
           * @param  {...any} args 剩余參數
           * @returns 
           */
          Function.prototype.binCall=function(context, ...args) {
            if (typeof this !=='function') console.error('type Error'); // 1
            context=(context!==null && context!==undefined) ? Object(context) : window
              
            context.fn=this // 2
            
            const result=context.fn(...args)  // 3
            delete context.fn;
            return result
          }
          

          5. 測試代碼

          // 測試
          function sum(num1, num2) {
            console.log('sum 被執行', this);
            return num1 + num2
          }
          
          // 原生的 call() 方法
          console.log(sum.call({name: 'bin'},1,2));
          
          // 自定義的 binCall() 方法
          console.log(sum.binCall({name: 'bin'},1,2));
          

          經過原生的call方法和手寫的binCall方法測試,我們手動實現的binCall方法也能實現原生call方法的功能

          6. 細節解析

          1. this 指向的就是調用 binCall() 的那個函數(隱式綁定);
          2. 傳入的 context 參數表示:將 this 的指向改為這個參數;
          3. 改變 this 指向其實就是在 context 上添加一個臨時的方法,值為 this
          4. 調用 context.fn() 時,就已經改變了 this 的指向,同時得使用展開運算符傳入參數
          5. delete context.fn 刪除那個臨時方法是因為已經不需要用了

          7. 核心原理

          通過在傳入的對象上,臨時新增一個方法,這個方法的值是當前 binCall 的調用者。然后 context.fn(...argArray) 調用這個函數,通過隱式綁定的方式改變了 this 的指向,最后得到結果并返回

          點擊下方,第一時間了解華為云新鮮技術~

          華為云博客_大數據博客_AI博客_云計算博客_開發者中心-華為云


          主站蜘蛛池模板: 一区二区三区中文| 性色A码一区二区三区天美传媒| 久久精品无码一区二区三区| 亚洲av乱码一区二区三区| 中文无码AV一区二区三区| 精彩视频一区二区| 国产精品一区二区在线观看| 2018高清国产一区二区三区 | 亚洲av无码一区二区三区在线播放| 精品国产一区二区三区2021| 国产激情一区二区三区在线观看| 日本一区二区视频| 无码中文字幕一区二区三区| 精品一区二区三区在线播放视频| 一区二区三区国产精品 | 国产精品亚洲一区二区在线观看 | 久久精品一区二区三区中文字幕| 美女视频一区二区| 杨幂AV污网站在线一区二区| 波多野结衣一区二区三区88| 男人的天堂亚洲一区二区三区 | 日本精品高清一区二区| 红桃AV一区二区三区在线无码AV| 变态拳头交视频一区二区| 大伊香蕉精品一区视频在线 | 国产高清不卡一区二区| 久久精品视频一区二区三区| 一区二区在线视频| 亚洲AV一区二区三区四区| 精品一区狼人国产在线| 日本一区二区在线不卡| 亚洲AV无码一区二三区| 中文字幕一精品亚洲无线一区| 亚洲AV乱码一区二区三区林ゆな| 日产精品久久久一区二区| 日本无码一区二区三区白峰美| 国产伦精品一区三区视频| 国模丽丽啪啪一区二区| 色一乱一伦一图一区二区精品| 一区二区三区视频| 天天看高清无码一区二区三区 |