91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

JS之如何處理new的情況

發布時間:2022-07-11 09:24:20 來源:億速云 閱讀:208 作者:iii 欄目:開發技術

這篇文章主要介紹“JS之如何處理new的情況”,在日常操作中,相信很多人在JS之如何處理new的情況問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JS之如何處理new的情況”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

JS 中 bind 方法實現:
Function.prototype.myBind = function(thisArg, ...prefixArgs) {
  const fn = this;
  return function(...args) {
    return fn.call(thisArg, ...prefixArgs, ...args);
  }
}

但沒有處理 通過 new 創建實例 的情況。

因為很少會遇到給 bind 返回的函數做 new 操作的場景。

new

我們先學習一下 new 操作符。

new 用于通過函數來創建一個對象實例,在很多語言中都能看到。

JS 的函數,除了可以是普通函數,比如:

function sum(a, b) {
  return a + b;
}

還可以是構造函數,只需要在構造時在它前面加一個 new:

function Person(name, age) {
 this.name = name;
 this.age = age;
}

const person = new Person('前端西瓜哥', 100)
// Person {name: '前端西瓜哥', age: 100}

new 創建一個新對象,做了下面幾件事:

  • 創建一個空對象 {}

  • 空對象的原型屬性 __proto__ 指向構造函數的原型對象 Person.prototype

  • 函數中的 this 設置為這個空對象;

  • 如果該函數不返回一個對象,就返回這個 this,否則返回這個對象。

判斷函數是否通過 new 被調用

怎么判斷一個函數正在被 new 操作符調用?

答案是 使用 instanceof 判斷 this 是否為當前函數的實例,即 this instanceof Fn 為 true,表示在通過 new 構建實例。

我們看一個例子:

function Person() {
  if (this instanceof Person) {
    console.log('通過 new 構建實例');
  } else {
    console.log('普通調用')
  }
}

Person()     // 輸出:普通調用
new Person() // 輸出:通過 new 構建實例

在 Vuejs 的源碼,你會看到下面代碼,這里也用到了這個技巧。

function Vue(options) {
  if (__DEV__ && !(this instanceof Vue)) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

你在開發環境如果不通過 new 來使用 Vue 對象,會在控制臺提示你要通過 new 來調用 Vue。

new 和 bind

如果我們 new 的是 Function.prototype.bind 返回的新函數,會發生什么事情?

function Person(name, age) {
 this.name = name;
 this.age = age;
}

const BoundPerson = Person.bind(null, '前端西瓜哥');
const boundPerson = new BoundPerson(100);
// Person {name: '前端西瓜哥', age: 100}

boundPerson.__proto__ === Person.prototype
// true

結果等價于直接去 new 原始函數。

不同的是,仍舊可以進行參數的預置。可以看到,構造函數的第一個參數,在調用 bind 的時候就提前設置為 '前端西瓜哥'。

實現完整的 bind

完整實現如下:

Function.prototype.myBind = function(thisArg, ...prefixArgs) {
  const fn = this;
  const boundFn = function(...args) {
    // 通過 new 使用當前函數
    if (this instanceof boundFn) {
      return new fn(...prefixArgs, ...args);
    }
    // 普通的方法調用當前函數
    return fn.call(thisArg, ...prefixArgs, ...args);
  }
  boundFn.prototype = fn.prototype;
  return boundFn;
}

這里我通過 this instanceof boundFn 來判斷是否用了 new,如果是,就直接 new 原始函數然后返回,記得帶上 bind 預置好的參數。

其他保持原樣。

boundFn.prototype = fn.prototype;  這個可寫可不寫,只是讓 bind 返回的新函數的 prototype 指向原函數的 prototype。

如果是原生 bind 返回的函數,它是沒有 protoype 屬性的,可以認為它是一種特別的函數,而我們實現的 bind 返回的卻是一個普通函數,所以并不能完全模擬的。

如果你 追求完美的實現,可以研讀一下  Function.prototype.bind 的標準:

然后再看看知名的 core.js 庫中對 bind 的實現:

其中核心實現為:

// `Function.prototype.bind` method implementation
// https://tc39.es/ecma262/#sec-function.prototype.bind
module.exports = Function.bind || function bind(that /* , ...args */) {
  var F = aCallable(this);
  var Prototype = F.prototype;
  var partArgs = arraySlice(arguments, 1);
  var boundFunction = function bound(/* args... */) {
    var args = concat(partArgs, arraySlice(arguments));
    return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
  };
  if (isObject(Prototype)) boundFunction.prototype = Prototype;
  return boundFunction;
};

這里有更多的細節:

  • 這里判斷了 this 是否為函數類型,不是函數會報錯;

  • F.prototype 需要是一個對象或函數,才能賦值給新函數;

  • 使用了普通函數和 arguments,這是為了兼容 ES5。

到此,關于“JS之如何處理new的情況”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

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

AI

清苑县| 赞皇县| 周至县| 嘉峪关市| 玛曲县| 大渡口区| 南丹县| 金寨县| 博野县| 遂溪县| 双城市| 阳春市| 玉龙| 广宁县| 会宁县| 呈贡县| 灵璧县| 思茅市| 兴文县| 云和县| 鄂托克前旗| 新平| 于田县| 西乌珠穆沁旗| 搜索| 额尔古纳市| 灵宝市| 太仓市| 贺州市| 元谋县| 诏安县| 淅川县| 海伦市| 肇州县| 汉沽区| 福州市| 通江县| 明溪县| 资中县| 开鲁县| 通州区|