【问题标题】:Why is my ES module function undefined sometimes为什么有时我的 ES 模块功能未定义
【发布时间】:2020-07-30 08:01:44
【问题描述】:

我有以下初始化 Google Charts 的 ES 模块。

mychart.js

let redraw;

function init(data) {
    // Do stuff to populate the chart
    // [...]
    // Set the redraw function which will be called on resize
    redraw = () => chart.draw(data, chartOptions);
    redraw();
    $(window).resize(redraw);
}

export default { redraw, init, [...] };

main.js

import Mychart from './mychart';

$('#specific-button').on('click', function() {
    $('#chart-container').toggle(function() {
        // Also call redraw function when toggling HTML container visible
        if ($('#chart-container').is(':visible')) {
            Mychart.redraw();
        }
    });
});

$.ajax(/* Some ajax query */,
    success: function(data) {
        // First init of the Chart
        Mychart.init(data);
    }
);

当我的网页显示时,图表可以正常工作,并且在 window.resize 事件上正确调整大小。但是当我单击#specific-button 元素时,它会抛出undefined 错误。有什么办法解决这个问题?

main.js?dbbb:47 Uncaught TypeError: _main_mychart__WEBPACK_IMPORTED_MODULE_1__.default.redraw is not a function

【问题讨论】:

    标签: javascript ecmascript-6 es6-modules


    【解决方案1】:

    在您从模块中导出对象时,redraw 的值是 undefined。稍后为变量分配不同的值不会更新对象。简单例子:

    var foo;
    var bar = {foo};
    foo = 42;
    console.log(bar);

    您可以预先定义对象并更新对象:

    const chart = {};
    
    function init(data) {
        // Do stuff to populate the chart
        // [...]
        // Set the redraw function which will be called on resize
        chart.redraw = () => chart.draw(data, chartOptions);
        chart.redraw();
        $(window).resize(chart.redraw);
    }
    chart.init = init;
    
    export default chart;
    

    或者您可以改用命名导出(它们是“实时”绑定):

    export let redraw;
    
    export function init(data) {
        // Do stuff to populate the chart
        // [...]
        // Set the redraw function which will be called on resize
        redraw = () => chart.draw(data, chartOptions);
        redraw();
        $(window).resize(redraw);
    }
    

    main.js:

    import * as Mychart from './mychart';
    

    话虽如此,更好的方法(在这两种情况下)是使用空函数初始化redraw,以便它始终具有适当的值(在图表初始化之前它不会做任何事情)。

    【讨论】:

    • 很好奇,为什么命名导出是“实时绑定”,而默认导出不是实时绑定?他们本质上不是完成同样的事情吗,只是一个导入所有内容?
    • @p32094:默认导出也是生命绑定。默认导出只是一个名为“default”的命名导出。
    • 好的,所以我最初创建的对象 { redraw, init, blabla... } 是 Life bound,但是该对象中 redraw 的引用是错误的?
    • @Marc:是的。当您使用变量初始化对象属性时,变量的当前值被复制到对象中。与值来自的变量没有内在联系。 JavaScript 是一种“按值传递”的语言(我猜导入/导出是一种例外)。
    • @Marc:我会这么说。这也允许组件只导入他们需要的东西,例如import {redraw} from bla.
    猜你喜欢
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 2017-11-17
    相关资源
    最近更新 更多