整合營銷服務商

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

          免費咨詢熱線:

          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博客_云計算博客_開發者中心-華為云


          主站蜘蛛池模板: 在线日产精品一区| 中文字幕无码免费久久9一区9| 亚洲熟女综合色一区二区三区| 国产精品视频一区二区三区经| 国产精品99精品一区二区三区| 综合激情区视频一区视频二区| 精品国产一区二区三区在线观看 | 一级特黄性色生活片一区二区| 中文字幕在线无码一区| 久久久老熟女一区二区三区| 欧美av色香蕉一区二区蜜桃小说 | 无码一区二区三区老色鬼| 国产精品综合AV一区二区国产馆| 国产一区二区三区樱花动漫| 内射女校花一区二区三区| 精品国产一区二区三区香蕉 | 久久婷婷色一区二区三区| 尤物精品视频一区二区三区 | 久久久久人妻一区精品| 精品无码AV一区二区三区不卡| 在线不卡一区二区三区日韩| 日韩亚洲一区二区三区| 精品无码国产AV一区二区三区 | 一区二区免费国产在线观看| 无码人妻AⅤ一区二区三区| 国产精品一区二区在线观看| 国产精品视频一区二区三区无码| 理论亚洲区美一区二区三区| 亚洲AV乱码一区二区三区林ゆな| 日韩精品一区二区三区中文3d| 亚洲韩国精品无码一区二区三区| 亚洲愉拍一区二区三区| 伊人精品视频一区二区三区| 国模精品视频一区二区三区| 国产激情无码一区二区| 狠狠爱无码一区二区三区| 亚欧免费视频一区二区三区| 成人区精品一区二区不卡| 免费高清av一区二区三区| 日本一区二区在线播放| 久久精品一区二区三区中文字幕|