簡體   English   中英

JavaScript:覆蓋整個類的構造函數中定義的屬性

[英]JavaScript: Overwrite property defined in constructor for whole class

我正在嘗試覆蓋一個類的功能:

class MyClass {
  constructor() {
    // more code
  }

  myFunction = function() {
    console.log('not this')
  }
}

// can't change the code above

MyClass.prototype.myFunction = function() {
  console.log('it should print this')
}

new MyClass().myFunction()

但是 Babel 將上面的內容編譯為:

class MyClass {
  constructor() {
    // more code

    this.myFunction = function () {
      console.log('not this');
    };
  }
}

// can't change the code above

MyClass.prototype.myFunction = function () {
  console.log('it should print this');
};

new MyClass().myFunction();

因為函數在原始代碼中被定義為屬性,所以 Babel 將該定義放在構造函數中。 如果我理解正確,原型只包含函數,而不是所有屬性。 因為構造函數在對象從原型派生之后運行,所以我不能使用原型來覆蓋該函數。

我的第二次嘗試是覆蓋構造函數:

class MyClass {
  constructor() {
    // more code
  }

  myFunction = function () {
    console.log('not this')
  }
}

// can't change the code above

let oldConstructor = MyClass.prototype.constructor
MyClass.prototype.constructor = function() {
  // call old constructor first, it will set myFunction
  oldConstructor()

  // now overwrite myFunction
  this.myFunction = function () {
    console.log('it should print this')
  }
}

new MyClass().myFunction()

好吧,讓我們試試……用 Babel 編譯,保存到 test.js 並運行:

~> node test.js
not this

我試圖使這個問題盡可能籠統。 關於為什么我不能在特定情況下更改類的更多背景信息:該類實際上來自我正在使用的庫,而我使用的其他包也依賴於該庫。 MeteorJS 需要包來指定其依賴項的確切版本和來源,這就是我不能使用 fork 的原因:我必須 fork 依賴於這個庫的每個包。

實際上,您正在更改您的課程,但它“沒有生效”,因為javascript 解釋器如何在其對象中查找信息 首先,對象內部的屬性,然后是原型鏈。

在您的第一個示例中,如果您“刪除”本地屬性,您的更改就會生效。 例子:

class MyClass {
  constructor() {
    // more code

    this.myFunction = function () {
      console.log('not this');
    };
  }
}

// can't change the code above

MyClass.prototype.myFunction = function () {
  console.log('it should print this');
};

const obj = new MyClass();
delete obj.myFunction;
obj.myFunction();

https://jsbin.com/gixufadewu/edit?js,console

這是無法做到的。 每當您實例化MyClass時,內部的myFunction都會被重新定義。 但不是原型鏈中定義的myFunction 所以解釋器會先在實例中查找方法,然后在原型鏈中查找。 在原型鏈中定義可以被 JavaScript 繼承覆蓋的methods

例如:

var a = new MyClass();
var b = new MyClass();

a.myFunction() === b.myFunction(); //false

a.__proto__.myFunction() === b.__proto__.myFunction() //true

由於原始問題沒有解決方案,我最終使用了這個:

class MyClass {
  myFunction = function() {
    console.log('not this')
  }
}

class MyNewClass extends MyClass {
  myFunction = function() {
    console.log('should print this')
  }
}

new MyNewClass().myFunction()

顯然,我現在總是必須使用 MyNewClass,這是我並不真正想要的,並且最初的問題要求解決方案來覆蓋現有 Class 的功能,但這在我的情況下有效。

您可以做的是通過在原型上放置一個 getter/setter 來攔截分配:

function myFunction() {
  console.log('it should print this');
}
Object.defineProperty(MyClass.prototype, "myFunction", {
  set(val) { /* ignore */ },
  get() { return myFunction; }
});

或者,您可以裝飾構造函數,但對於 ES6 類,這意味着額外的預防措施

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM