中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript的案例分析

發布時間:2020-11-02 11:48:52 來源:億速云 閱讀:162 作者:小新 欄目:web開發

這篇文章主要介紹javascript的案例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

我們經常在框架級的源碼中看到類似如下的一句代碼,比如:

var toStr1 = Function.prototype.call.bind(Object.prototype.toString);

在這一句代碼中既使用call方法,同時也使用bind方法,乍看之下,有點暈!這到底是想干嘛?

無妨,我們調用看看,傳入不同的類型試試,效果如下:

console.log(toStr1({}));      // "[object Object]"console.log(toStr1([]));      // "[object Array]"console.log(toStr1(123));     // "[object Number]"console.log(toStr1("abc"));   // "[object String]"console.log(toStr1("abc"));   // "[object String]"console.log(toStr1(new Date));// "[object Date]"復制代碼

從結果中可以看到該方法的主要功能是用于檢測對象的類型。但通常類型檢測,我們可能更多地看到如下代碼實現:

var toStr2 = obj => Object.prototype.toString.call(obj);console.log(toStr2({}));      // "[object Object]"console.log(toStr2([]));      // "[object Array]"console.log(toStr2(123));     // "[object Number]"console.log(toStr2("abc"));   // "[object String]"console.log(toStr2("abc"));   // "[object String]"console.log(toStr2(new Date));// "[object Date]"復制代碼

熟悉bind和call的同學應該知道,兩種方法本質上是相同的,而第二種方法更簡潔,僅僅使用一次call就能獲得我們想要的功能,且代碼邏輯清晰,理解起來更加容易,可在眾多框架中為何更多使用第一種呢?

其實主要的原因是防止原型污染,比如我們在業務代碼中覆寫了Object.prototype.toString方法,第二種寫法將得不到正確的結果,而第一種寫法仍然可以。我們用代碼來來試試:

var toStr1 = Function.prototype.call.bind(Object.prototype.toString);var toStr2 = obj => Object.prototype.toString.call(obj);Object.prototype.toString = function(){  return'toString方法被覆蓋!';
}// 接著我們再調用上述方法// toStr1調用結果如下:console.log(toStr1({}));      // "[object Object]"console.log(toStr1([]));      // "[object Array]"console.log(toStr1(123));     // "[object Number]"console.log(toStr1("abc"));   // "[object String]"console.log(toStr1("abc"));   // "[object String]"console.log(toStr1(new Date));// "[object Date]"// toStr2調用結果如下:console.log(toStr2({}));      // "toString方法被覆蓋!"console.log(toStr2([]));      // "toString方法被覆蓋!"console.log(toStr2(123));     // "toString方法被覆蓋!"console.log(toStr2("abc"));   // "toString方法被覆蓋!"console.log(toStr2("abc"));   // "toString方法被覆蓋!"console.log(toStr2(new Date));// "toString方法被覆蓋!"復制代碼

javascript的案例分析

javascript的案例分析

結果很明顯。第一種方法仍然能正確得到結果,而第二種則不行!那么為什么會這樣呢?我們知道bind函數返回結果是一個函數,這個函數是函數內部的函數,會被延遲執行,那么很自然聯想到這里可能存在閉包!因為閉包可以保持內部函數執行時的上下文狀態。不過在現代版瀏覽器中call和bind都已經被js引擎內部實現了,我們沒有辦法調試!但是我們可以通過polly-fill提供的近似實現的源碼來理解引擎內部的邏輯,下面是本文調試的demo,大家可以嘗試下:

// 模擬實現call// ES6實現Function.prototype.mycall = function (context) {
  context = context ? Object(context) : window;  var fn = Symbol();
  context[fn] = this;  let args = [...arguments].slice(1);  let result = context[fn](...args);  delete context[fn]  return result;
}// 模擬實現bindFunction.prototype.mybind = function (context) {  if (typeof this !== "function") {    throw new Error("請使用函數對象調用我,謝謝!");
  }  var self = this;  var args = Array.prototype.slice.call(arguments, 1);  var fNOP = function () { };  var fBound = function () {    var bindArgs = Array.prototype.slice.call(arguments);    return self.myapply(this instanceof fNOP ? this : context, args.concat(bindArgs));
  }

  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();  return fBound;
}// 模擬實現apply// ES6實現Function.prototype.myapply = function (context, arr) {
    context = context ? Object(context) : window;    var fn = Symbol();
    context[fn] = this;    let result;    if (!arr) {
        result = context[fn]();
    } else {
        result = context[fn](...arr);
    }    delete context[fn]    return result;
}var toStr1 = Function.prototype.mycall.mybind(Object.prototype.toString);console.log(toStr1({}));      // "[object Object]"console.log(toStr1([]));      // "[object Array]"console.log(toStr1(123));     // "[object Number]"console.log(toStr1("abc"));   // "[object String]"console.log(toStr1(new Date));// "[object Date]"復制代碼

javascript的案例分析

上述的實現略去一些健壯性的代碼,僅保留核心邏輯,具體的實現細節這里不做解釋,有興趣的可以自己研究,從devtools我們看到mybind形成的閉包確實在函數對象toStr1的作用域上!

當然如果你對原型鏈有深刻理解的話,其實這句有趣的代碼還可以寫成如下方式:

var toStr3 = Function.call.bind(Object.prototype.toString);var toStr4 = Function.call.call.bind(Object.prototype.toString);var toStr5 = Function.call.call.call.bind(Object.prototype.toString);// 甚至可以這么寫。。。var toStr6 = (()=>{}).call.bind(Object.prototype.toString);復制代碼

-END-

以上是javascript的案例分析的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄骅市| 清丰县| 江城| 密云县| 渑池县| 桂平市| 望谟县| 磴口县| 贺兰县| 彰化县| 博客| 瓦房店市| 宣化县| 陇川县| 莒南县| 章丘市| 奎屯市| 枣庄市| 平利县| 金山区| 丰顺县| 墨竹工卡县| 丰宁| 安国市| 成武县| 老河口市| 墨玉县| 土默特左旗| 镇平县| 安庆市| 松滋市| 宁陕县| 新泰市| 永吉县| 志丹县| 延长县| 综艺| 彭山县| 建阳市| 城市| 雷州市|