【问题标题】:How to access a class if you have a string of its name in javascript?如果您在 javascript 中有一个类的名称字符串,如何访问该类?
【发布时间】:2023-03-04 18:15:02
【问题描述】:

在 javascript 中,如果我有 2 个字符串 myAppmy-app 并被告知 myApp 实际上是扩展 HTMLElement 的类的名称,而 my-app 是该类的标记名,我该怎么做使用 JavaScript 来验证(假设该类已经定义)?

如果确实已经定义,基本上测试应该通过

class myApp extends HTMLElement {
    constructor() {
        super();
    }
}

customElements.define('my-app', myApp); 

基本上,它需要检查 myApp 是一个类并且确实扩展了 HTMLElement(尽管它可能会扩展其他东西,例如 Polymer.Element 等,但最终,它必须扩展 @987654330 @)。

其次,它必须检查my-app是那个类的标签名。

如何在 javascript 中做到这一点?

我试过eval("myApp"),但没用。

【问题讨论】:

  • 对于第一部分,如果 myApp 的祖先中有 HTMLElement,myApp.prototype instanceof HTMLElement 应该返回 true
  • 我不能 100% 确定 Polymer.Element 是否扩展了 HTMLElement,所以我可能会做 myApp.prototype instanceof HTMLElement || myApp.prototype instanceof Polymer.Element。但其他部分我不知道。
  • 我试过Polymer.Element instanceof HTMLElement,这显然是错误的。
  • 如果 myApp 扩展 Polymer.Element 扩展 HTMLElement,那么 HTMLElement 仍然是 myApp 的祖先 ... instanceof 不会检查一级祖先:p
  • “否决”描述?如果您要连续“否决”,您也可以留下您的理由。既然你的行为显然有合理的理由,为什么还要自己保密?

标签: javascript string class web-component custom-element


【解决方案1】:

您可以使用customElements.get() 从标签名称中获取自定义元素类。

class myApp extends HTMLElement {
  constructor() {
    super()
  }
}
customElements.define( 'my-app', myApp )

console.log( customElements.get( 'my-app' ) === myApp )  //true

【讨论】:

    【解决方案2】:

    好吧,我想通了,我可以做

        var worked = false;
        var claimedClassName = 'myApp';
        var claimedElementName = 'my-app'; 
    
        try {
            const r = new Function(`return ${claimedClassName}`)();
            if (!(r.prototype instanceof HTMLElement)) {
                throw new Error('Class is not instance of HTMLElement');
            }
            var a = new r();
            if (a.tagName.toLowerCase() != claimedElementName.toLowerCase()) {
                throw new Error('Tagname does not match');
            }
            worked = true;
        } catch (err) {
            alert(err.message + "\n" + err.stack);
        }
    
        if (worked) alert("pass!")
        else alert("fail!");
    

    【讨论】:

    • 如果您的答案解决了问题,您可以接受自己的答案stackoverflow.com/help/self-answer
    • 你的函数版本可能更好。我会接受你的。
    • 我在 Chrome 中实现了自定义元素,我认为您的代码有问题。 IIRC 标记名称是 ASCII 小写的,但你使用 toLowerCase 我认为它也是小写的非 ASCII。 customElements.get 简单直接——使用它。
    【解决方案3】:

    要检查class 是否存在并且extends HTMLElement 应该在与class 相同的范围内执行检查,方法是尝试使用const 声明myApp,这应该抛出一个@ 987654327@或使用console.assert()

    验证第一部分后,您可以创建元素并检查创建元素的.is 属性或.tagName

    class myApp extends HTMLElement {
        constructor() {
            super();
        }
    }
    
    customElements.define('my-app', myApp); 
    
    // string
    let str = "myApp";
    // get the object, if the object exists
    const myApp_ = new Function(`return ${str}`)();
    // check if `myApp` exists
    console.assert(myApp_ === void 0
    , myApp_
    , [`${myApp_} is defined`
      , new RegExp(`${str} extends HTMLElement`).test(`${myApp_}`)]);

    【讨论】:

    • 这里的问题是你没有引用类名myApp。你只有字符串“myApp”和“my-app”。
    • @omega 这不是“问题”。如果您没有字符串,那将是一个问题。将假定的class 标识符作为字符串作为标识符传递给console.assert() 以获得Boolean 评估并将字符串作为标识符作为第二个参数传递以获得class 的字符串表示形式
    • 我不确定我是否遵循,你能举个例子吗?您上面的代码使用变量名而不是字符串“myApp”和“my-app”。
    • @omega “我不确定我是否遵循,你能举个例子吗?”参见 stacksn-ps。 “您上面的代码使用变量名而不是字符串“myApp”和“my-app”。” 是的,一旦您有了字符串,就将字符串作为标识符传递给console.assert()
    • @omega 目前的stacksn-ps答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多