簡體   English   中英

獲取 ES6 class 實例的 class 名稱

[英]Get the class name of ES6 class instance

是否有任何“和諧”的方法可以從 ES6 class 實例中獲取 class 名稱? 以外

someClassInstance.constructor.name

目前我指望 Traceur 實施。 而且似乎 Babel 有一個用於 Function.name 的Function.name ,而 Traceur 沒有。

綜上所述:在 ES6/ES2015/Harmony 中沒有其他方法,在 ES.Next 中沒有任何預期的 ATM。

它可能為未縮小的服務器端應用程序提供有用的模式,但在用於瀏覽器/桌面/移動的應用程序中是不需要的。

Babel使用core-jsFunction.name ,應該為 Traceur 和 TypeScript 應用程序手動加載它。

someClassInstance.constructor.name正是這樣做的正確方法。 轉譯器可能不支持這一點,但這是規范中的標准方式。 (通過 ClassDeclaration 產生式聲明的函數的name屬性在14.5.15 的第 6 步中設置。)

正如@Domenic 所說,使用someClassInstance.constructor.name @Esteban 在評論中提到

someClassInstance.constructor是一個函數。 所有函數都有一個name屬性...

因此,要靜態訪問類名,請執行以下操作(這適用於我的 Babel 版本 BTW。根據 @Domenic 上的評論,您的里程可能會有所不同)。

class SomeClass {
  constructor() {}
}

var someClassInstance = new SomeClass();
someClassInstance.constructor.name;      // === 'SomeClass'
SomeClass.name                           // === 'SomeClass'

更新

Babel 很好,但丑化/縮小最終給我帶來了問題。 我正在制作一個游戲,並且正在創建一個池化 Sprite 資源的散列(其中鍵是函數名稱)。 縮小后,每個函數/類都被命名為t 這會殺死哈希。 我在這個項目中使用了Gulp ,在閱讀了gulp-uglify 文檔后,我發現有一個參數可以防止這個局部變量/函數名稱重整的發生。 所以,在我的 gulpfile 中我改變了

.pipe($.uglify()).pipe($.uglify({ mangle: false }))

這里需要權衡性能與可讀性。 不修改名稱將導致(稍微)更大的構建文件(更多網絡資源)和可能更慢的代碼執行(需要引用 - 可能是廢話)。 另一方面,如果我保持不變,我將不得不在每個 ES6 類上手動定義getClassName - 在靜態和實例級別。 不,謝謝!

更新

在評論中的討論之后,似乎避免使用.name約定以支持定義這些函數是一個很好的范例。 它只需要幾行代碼,並且可以完全縮小和通用您的代碼(如果在庫中使用)。 所以我想我改變主意了,將在我的類上手動定義getClassName 謝謝@estus! . 無論如何,與直接變量訪問相比,Getter/Setter 通常是一個好主意,尤其是在基於客戶端的應用程序中。

class SomeClass {
  constructor() {}
  static getClassName(){ return 'SomeClass'; }
  getClassName(){ return SomeClass.getClassName(); }
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.getClassName();      // === 'SomeClass' (static fn)
someClassInstance.getClassName();                  // === 'SomeClass' (instance fn)
SomeClass.getClassName()                           // === 'SomeClass' (static fn)

直接從類中獲取類名

以前的答案解釋了someClassInstance.constructor.name工作得很好,但是如果您需要以編程方式將類名轉換為字符串並且不想為此創建實例,請記住:

typeof YourClass === "function"

而且,由於每個函數都有一個name屬性,另一種使用類名獲取字符串的好方法是:

YourClass.name

下面是一個很好的例子,說明為什么這很有用。

加載 Web 組件

正如MDN 文檔告訴我們的那樣,這是加載 Web 組件的方式:

customElements.define("your-component", YourComponent);

其中YourComponent是從HTMLElement擴展的類。 由於在組件標簽本身之后命名組件的類被認為是一種很好的做法,因此最好編寫一個所有組件都可以用來注冊自己的輔助函數。 所以這是那個函數:

function registerComponent(componentClass) {
    const componentName = upperCamelCaseToSnakeCase(componentClass.name);
    customElements.define(componentName, componentClass);
}

所以你需要做的就是:

registerComponent(YourComponent);

這很好,因為它比自己編寫組件標簽更不容易出錯。 總結一下,這是upperCamelCaseToSnakeCase()函數:

// converts `YourString` into `your-string`
function upperCamelCaseToSnakeCase(value) {
    return value
        // first char to lower case
        .replace(/^([A-Z])/, $1 => $1.toLowerCase())
        // following upper chars get preceded with a dash
        .replace(/([A-Z])/g, $1 => "-" + $1.toLowerCase());
}

用於 babel 轉譯(縮小前)

如果您將 Babel 與@babel/preset-env ,則可以保留類定義而不將它們轉換為函數(這會刪除constructor屬性)

您可以在babel.config / babelrc刪除與此配置的舊瀏覽器兼容性:

{
  "presets": [
    ["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
  ]
}

有關targets更多信息: https : //babeljs.io/docs/en/babel-preset-env#targets

用於 babel 縮小(轉譯后)

看起來現在沒有簡單的解決方案......我們需要看看重整排除。

如果您可以控制 class 的實施

我在這里添加這個,因為當我試圖弄清楚如何做到這一點時,它是谷歌的頂部。

這似乎在節點中為我工作。

./SuperClass.js

'use strict';

/**
 * A super class
 *
 * To show that it works with inheritance too
 *
 * In my usage, I'm also extending the Error class
 */
module.exports = class SuperClass extends Error {
    constructor(message, options = {}) {
        super(message);
        this.name = this.constructor.name;
        // ...other shared construction functionality
    }
};

./SubClass.js

'use strict';

const SuperClass = require('./SuperClass');
/**
 * a sub class
 */
module.exports = class SubClass extends SuperClass {
    constructor(message, options = {}) {
        super(message, options);
        // ... specific sub class construction functionality
    }
};
SubClass.name; // -> 'SubClass'
let instance = new SubClass('message');
instance.name; // -> 'SubClass'

顯然,這僅適用於您可以完全控制實現的類。

我可能會將其更改為_name或其他內容,但這是為了使其與我正在使用的另一個庫保持一致。

暫無
暫無

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

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