重新加载es6类

时间:2018-01-29 20:15:23

标签: javascript es6-class

我正在尝试加载外部JavaScript,使用它做一些工作,删除它并再次加载它。但是我遇到了问题,也许有人可以帮我理解原因。

以下是要加载的外部脚本的示例:

class ClassA {
    constructor() {
        console.log("ClassA object created");
    }
}

以下是我正在尝试用它做的一个例子:

let aScript = document.createElement("script");

aScript.onload = function() {

    //test ClassA object
    let classA = new ClassA(); //OK (ClassA object created)
    classA = null //OK

    //remove/delete the script
    document.head.removeChild(aScript); //OK
    delete ClassA; //OK
    ClassA = null; //OK
    window.ClassA = null //OK

    //Try to reload the same script...
    aScript = document.createElement("script");
    aScript.src = "ClassA.js";
    document.head.appendChild(aScript);
    //...throws error: (ClassA.js:1 Uncaught SyntaxError: Identifier 
    //'ClassA' has already been declared at VM1088 ClassA.js:1)
};

aScript.src = "ClassA.js"; //loading the script for the first time.
document.head.appendChild(aScript);

虽然我正在删除/删除脚本,但仍在内存中引用类对象(ClassA)。

Uncaught SyntaxError: Identifier 'ClassA' has already been declared

是否可以从内存中删除es6类?我做错了什么?

感谢。

修改

要加载的脚本的解决方案:

window.ClassA = class {
    constructor() {
        console.log("ClassA object created");
    }
}

(function(window) {
    class ClassA {
        constructor() {
            console.log("ClassA object created");
        }
    }
}(window))

这样可以再次加载,删除和加载相同的脚本/类。有关详细信息,请参阅traktor53帖子。

1 个答案:

答案 0 :(得分:3)

不,无法从内存中删除ES6(ECMA2015)类声明。

关于script元素,JavaScript引擎在加载脚本后解析并运行脚本。运行脚本在全局范围内声明ClassA。删除脚本元素不会删除声明 - 以同样的方式删除已编译程序的源文件将不会删除已从其创建的对象或可执行文件。

ES6还引入了let变量,常量和类的特殊安排:它们是块作用域的,不能在同一个块或全局范围内重新声明。尝试这样做被认为是编程错误:

{    // in same block scope
     let sameName = "0"; // first declaration is ok, but
     let sameName = "0"; // syntax error: redeclartion of "sameName", or
     const sameName = 0; // syntax error: redeclaration of "sameName", or
     class sameName {};  // syntax error: redeclaration of "sameName", or
}

此外,与使用var声明的变量不同,使用letconstclass在全局范围内声明的块范围标识符不是全局属性对象

更新更正:类名称是读写的,其行为更像let而不是const声明。您可以使用赋值运算符('=')为类名指定新值 - 但尝试在全局范围内或同一块内第二次声明名称将引发错误。

用于演示类名声明的这些方面的代码片段:

class ClassA {
    constructor() {
        console.log("ClassA object created");
    }
};

console.log(ClassA); // the class
console.log("ClassA is a " + typeof ClassA); // function
console.log("window ClassA property: " + 
  ( window.hasOwnProperty("ClassA") ? "yes" : "no")
);
console.log("typeof window.ClassA " + typeof window.ClassA);
 
ClassA=null;
if( ClassA === null) {
    console.log( "ClassA is assignable");
}
else {
    console.log( "ClassA is not assignable");
}

尝试在上述代码段末尾重新声明classA将在解析代码时生成有关重新声明的错误 - 代码根本不会执行。

解决方案可以是使用类表达式将ClassA定义为全局对象属性:

// declare ClassA as a global property variable
window.ClassA =  class {
    constructor() {
        console.log("ClassA object created");
    }
}


console.log(ClassA); // the class
console.log(typeof ClassA); // function
delete window.ClassA; // remove global object property
console.log(typeof window.ClassA); // undefined

(未测试var声明而不是窗口属性。