无法使用 Webpack Encore 访问 window["var_name"]

Can't access window["var_name"] with Webpack Encore

根据下面的代码,我有一个变量 mdcDialog,它在页面加载后用 material-components-web (MDCDialog) 库初始化。

在表单提交时,默认事件被阻止,取而代之的是,ajaxSubmit() 处理表单。
响应是一个 json 对象,我可以从中找到变量 response.modal.modal 及其字符串值 mdcDialog.

但出于某种原因,console.info(window[response.modal.modal]); return 未定义而不是变量 mdcDialog
另一方面,执行 console.log(mdcDialog) 输出变量。

如果 window 不起作用,我如何从字符串响应访问我的变量 mdcDialog

app.js

/* --- VARS --- */
const page="#page";
let mdcDialog;

/* --- FUNCTIONS --- */
function ajaxSubmit(node) {
    $.ajax({
        type: node.attr("method"),
        url: node.attr("action"),
        enctype: "multipart/form-data",
        data: new FormData(node[0]),
        processData: false,
        contentType: false,
        cache: false
    }).done(function(response, status, xhr) {
        if(response !== false) {
            /** @var response.modal */
            if(typeof response.modal !== "undefined") {
                /** @var response.modal.action */
                /** @var response.modal.modal */
                /** @var response.modal.content */
                if(response.modal.action === "load") {
                    console.info(window[response.modal.modal]);
                }
            }
        }

    }).fail(function(request, status, error) {
        console.error(request);
        console.error(status);
        console.error(error);
    });
}

/* --- ACTIONS --- */
$(document).ready(function() {
    mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    $(page).on("submit", ".ajs", function(e) {
        e.preventDefault();
        ajaxSubmit($(this));
    })
});

你只是在这个函数的范围内定义了mdcDialog(如果javascript在"Strict Mode"中是运行):

$(document).ready(function() {
    mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

要赋予它全局范围并使其可通过 window['mdcDialog'] 访问,请执行以下操作:

$(document).ready(function() {
    window.mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

或者在函数前定义在全局范围内:

var mdcDialog;
$(document).ready(function() {
    mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

https://www.w3schools.com/js/js_scope.asp

您的 app.js 文件被视为一个 JavaScript 模块,这意味着您在其中声明的变量在默认情况下作用于该模块,而不是添加到 window(这通常是一件坏事。

如果你想在你的模块之外提供一些东西(在另一个文件中或从你的 HTML 页面/webtools),你可以设置 global.mdcDialog.

话虽如此,我不确定您在示例中要做什么...如果您需要访问在 $(document).ready 回调中创建的 mdc.dialog.MDCDialog 的实例,为什么会你不是直接用mdcDialog吗?

如果您的用例是 "I will have multiple dialogs and will need to retrieve the right one" 也许将所有实例存储在一个对象中是更好的方法:

const dialogs = {};

function ajaxSubmit(node) {
    $.ajax({
        // ...
    }).done(function(response, status, xhr) {
        // ...
        console.info(dialogs[response.modal.modal]);
    });
}

$(document).ready(function() {
    dialogs['mdcDialog'] = new mdc.dialog.MDCDialog(/* ... */);

    $(page).on("submit", ".ajs", function(e) {
        e.preventDefault();
        ajaxSubmit($(this));
    })
});

letconst定义的变量具有块作用域,即使定义在最外层作用域,也不会全局定义 因此 will never be accessible through the global (window) object.

为了让它们以这种方式访问​​,您必须使用var,或者在全局对象本身上定义它们。

let foo=1
window.foo //undefined
foo        //1

var bar=2
window.bar //2
bar        //2

window.baz=3
window.baz //3
baz        //3

有关详细信息,请参阅 this SO answer