【问题标题】:Javascript custom class method cannot call another method in same class after using BabelJavascript 自定义类方法在使用 Babel 后不能调用同一个类中的另一个方法
【发布时间】:2020-03-23 17:56:31
【问题描述】:

我对 JS 编程有点陌生,所以如果这很简单,请原谅我......但是我创建了一个具有各种方法和属性的类。但是,这段代码必须在 IE11 上运行,所以我使用 Babel 来定位并转换代码。我不熟悉它使用的语法,这可能是问题的一部分。我的问题是loadLocationChildren 方法不能调用_addLocations 方法。浏览器给我一个错误提示“this._addLocations is not a function”。 Babel 的输出文件如下:

"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }


var LocationDataManager = function () {

    const isBusyChanged = "ISBUSYCHANGED";
    const selectedLocationChanged = "SELECTEDLOCATIONCHANGED";

    function LocationDataManager() {
        _classCallCheck(this, LocationDataManager);

        this._locationData = {};
        this._selectedLocation = null;
        this._loadHierachyUrl = "";
        this._loadLocationUrl = "";
        this._loadChildrenUrl = "";
        this._isBusy = 0;
        this._errorHandlerFunc = null;
    }

    _createClass(LocationDataManager, [{
        key: "location",
        value: function location(locationId) {
            return this._locationData[locationId];
        }
    }, {
        key: "selectLocation",
        value: function selectLocation(locationId) {
            var f = this._locationData[locationId];
            if (f === undefined || f === null) throw Error("Location does not exist.");else this.selectedLocation = f;
        }
    }, {
        key: "loadLocation",
        value: function loadLocation(locationId) {

            if (isNullOrEmpty(locationId)) return null;
            if (isNullOrEmpty(this._loadLocationUrl)) return null;

            var found = this._locationData[locationId];
            if (found != null) return found;

            this.isBusy = true;

            $.post(this._loadLocationUrl, {
                id: locationId
            }, function (data) {

                this._addLocations(data);
                this.isBusy = false;
                return data;
            }).fail(function (error) {

                this.isBusy = false;
                this._errorHandlerFunc(error);
                return null;
            });
        }
    }, {
        key: "loadLocationChildren",
        //loads the children of a location into the map

        value: function loadLocationChildren(parentId) {

            if (isNullOrEmpty(this._loadChildrenUrl)) return null;

            var found = this._locationData[parentId];

            if (found != null && found.childrenLoaded == true) {
                return found.children;
            }
            this.isBusy = true;

            $.post(this._loadChildrenUrl, {
                id: parentId
            }, function (data) {

                this._addLocations(data);
                this.isBusy = false;
                return data;
            }).fail(function (error) {

                this.isBusy = false;
                this._errorHandlerFunc(error);
                return null;
            });
            return null;
        }
    }, {
        key: "loadHierarchy",
        //loads a location and all parents up to root into the map

        value: function loadHierarchy(locationId) {
            if (isNullOrEmpty(locationId)) return null;
            if (isNullOrEmpty(this._loadHierachyUrl)) return null;

            this.isBusy = true;
            $.post(this._loadHierachyUrl, {
                id: locationId
            }, function (data) {

                this._addLocations(data);
                this.isBusy = false;
                return data;
            }).fail(function (error) {

                this.isBusy = false;
                this._errorHandlerFunc(error);
                return null;
            });
            return null;
        }
    }, {
        key: "_addLocations",
        value: function _addLocations(data) {
            if (data === undefined || data === null || data.length === 0) return;

            for (var i = 0; i < data.length; i++) {
                var node = data[i];
                this._locationData[node.Id] = node;
            }
        }
    }, {
        key: "loadHierarchyUrl",
        get: function get() {
            return this._loadHierachyUrl;
        },
        set: function set(value) {
            this._loadHierachyUrl = value;
        }
    }, {
        key: "loadLocationUrl",
        get: function get() {
            return this._loadLocationUrl;
        },
        set: function set(value) {
            this._loadLocationUrl = value;
        }
    }, {
        key: "loadChildrenUrl",
        get: function get() {
            return this._loadChildrenUrl;
        },
        set: function set(value) {
            this._loadChildrenUrl = value;
        }
    }, {
        key: "errorHandlerFunc",
        set: function set(func) {
            this._errorHandlerFunc = func;
        }
    }, {
        key: "isBusy",
        get: function get() {
            return Boolean(this._isBusy);
        },
        set: function set(value) {
            if (Boolean(value)) this._isBusy++;else {
                this._isBusy--;
                if (this._isBusy < 0) this._isBusy = 0;
            }
            pubSub.publish(isBusyChanged, this.isBusy);
        }
    }, {
        key: "selectedLocation",
        get: function get() {
            return this._selectedLocation;
        },
        set: function set(value) {
            if (value == this._selectedLocation) return;
            this._selectedLocation = value;
            pubSub.publish(selectedLocationChanged, this._selectedLocation);
        }
    }]);

    return LocationDataManager;
}();

【问题讨论】:

  • $.post的回调中,上下文发生了变化,this不再是你类的实例。您是否在原始代码中使用箭头函数来确保保留上下文? (data) =&gt; { this._addLocation(data); /*...*/ }。然后 Babel 应该在将其转换回普通函数时处理它。 (对.fail 回调做同样的事情)
  • @blex 啊,有道理。我没有使用箭头,因为我之前遇到过它们和 IE11 的问题……但那是在我找到 Babel 之前。我会去改变它,希望它能解决它。感谢您的建议。

标签: javascript internet-explorer-11 babeljs


【解决方案1】:

在执行回调函数时,this 的上下文会丢失。要解决这个问题,您可以使用arrow function 或使用bind method

正如您所说,您没有使用箭头功能,那么您可以尝试bind 方法。我觉得应该是这样的:

$.post(..., function(data) { this._addLocations(data); ...}).bind(this);

有关如何在回调中访问正确的this的详细信息,您可以参考this thread,其中有非常详细的说明。

【讨论】:

  • 谢谢。根据之前的建议,我确实使用箭头函数来解决我遇到的问题。但是,我遇到了另一种情况,我不确定如何应用箭头运算符,但 bind 方法工作得很好!
猜你喜欢
  • 2017-10-17
  • 2011-01-15
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
相关资源
最近更新 更多