模擬實現new

new 運算符建立一個用戶定義的對象類型的實例或具備構造函數的內置對象的實例。瀏覽器

上面的定義有點抽象,咱們來經過一個例子看 new 運算符扮演的角色app

function Foo(name, age) {
  this.name = name;
  this.age = age;
}
Foo.prototype.getName = function() {
  return this.name;
};
Foo.prototype.foo = "foo";
var f = new Foo("zhangsan", 18);
f.getName(); // zhangsan
f.foo; // foo
複製代碼

上面經過 new 建立了一個新的對象,而且這個對象經過原型鏈訪問到了原型上的方法和屬性,因此 new 運算符就是執行構造函數返回一個實例對象。函數

new 運算符在執行時執行了下面四步:測試

  1. 建立一個空的簡單 JavaScript 對象(即{});
  2. 連接該對象(即設置該對象的構造函數)到另外一個對象 ;
  3. 將步驟 1 新建立的對象做爲 this 的上下文 ;
  4. 若是該函數沒有返回對象,則返回 this。

實現

根據上面的執行步驟咱們來嘗試實現下,固然 new 操做符確定是模擬不了了,下面經過函數的形式展現ui

function newCall(fn) {
  var args = Array.prototype.slice.call(arguments, 1);
  var obj = {};
  obj.__proto__ = fn.prototype;
  var result = fn.apply(obj, args);
  return result && typeof result === "object" ? result : obj;
}
複製代碼

Ok,到這裏就實現了一個模擬 new 的操做,咱們測試一下this

function Otaku(name, age) {
  this.name = name;
  this.age = age;

  this.habit = "Games";
}

Otaku.prototype.strength = 60;

Otaku.prototype.sayYourName = function() {
  console.log("I am " + this.name);
};

function newCall(fn) {
  var args = Array.prototype.slice.call(arguments, 1);
  var obj = {};
  obj.__proto__ = fn.prototype;
  var result = fn.apply(obj, args);
  return result && typeof result === "object" ? result : obj;
}

var person = newCall(Otaku, "Kevin", "18");

console.log(person.name); // Kevin
console.log(person.habit); // Games
console.log(person.strength); // 60
複製代碼

撒花 ✿✿ ヽ(°▽°)ノ ✿,不過額外提醒一下__proto__是瀏覽器實現的非標準屬性,通常狀況下不推薦使用,不過既然是模擬 es5 推薦的Object.setPrototypeOf確定沒辦法用了,只能將就着用了es5

相關文章
相關標籤/搜索