【问题标题】:Access object context from prototype functions JavaScript从原型函数 JavaScript 访问对象上下文
【发布时间】:2016-10-28 07:15:54
【问题描述】:

我有对象范围的问题。

这是我的课程代码

// Table list module
        function DynamicItemList(data, settings, fields) {
            if (!(this instanceof DynamicItemList)) {
                return new DynamicItemList(data, settings, fields);
            }
            this.data = data;
            this.settings = settings;
            this.fields = fields;
            this.dataSet = {
                "Result": "OK",
                "Records": this.data ? JSON.parse(this.data) : []
            };
            this.items = this.dataSet["Records"];
            this.generateId = makeIdCounter(findMaxInArray(this.dataSet["Records"], "id") + 1);
            this.dataHiddenInput = $(this.settings["hidden-input"]);
        }

        DynamicItemList.RESULT_OK = {"Result": "OK"};
        DynamicItemList.RESULT_ERROR = {"Result": "Error", "Message": "Error occurred"};
        DynamicItemList.prototype = (function () {
            var _self = this;
            var fetchItemsList = function (postData, jtParams) {
                return _self.dataSet;
            };
            var createItem = function (item) {
                item = parseQueryString(item);
                item.id = this.generateId();
                _self.items.push(item);
                return {
                    "Result": "OK",
                    "Record": item
                }
            };
            var removeItem = function (postData) {
                _self.items = removeFromArrayByPropertyValue(_self.items, "id", postData.id);
                _self.dataSet["Records"] = _self.items;
                _self.generateId = makeIdCounter(findMaxInArray(_self.dataSet["Records"], "id") + 1);
                return DynamicItemList.RESULT_OK;
            };
            return {
                setupTable: function () {
                    $(_self.settings["table-container"]).jtable({
                        title: _self.settings['title'],
                        actions: {
                            listAction: fetchItemsList,
                            deleteAction: removeItem
                        },
                        fields: _self.fields
                    });
                },
                load: function () {
                    $(_self.settings['table-container']).jtable('load');
                },
                submit: function () {
                    _self.dataHiddenInput.val(JSON.stringify(_self.dataSet["Records"]));
                }
            };
        })();

我在访问对象字段时遇到问题。

我尝试使用self 来维护调用范围。但是因为它首先从全局范围初始化,所以我得到了Window 对象保存在_self 中。

没有_self 只是有this 它也不起作用。因为我可以猜到我的函数fetchItemsList 是从jTable 上下文调用的,而这指向Window 对象,所以我收到错误undefined

我尝试了不同的方法,但都没有奏效。

请建议我该如何解决这个问题。

谢谢。

更新

这是所有方法都公开的版本。

            // Table list module
        function DynamicItemList(data, settings, fields) {
            if (!(this instanceof DynamicItemList)) {
                return new DynamicItemList(data, settings, fields);
            }
            this.data = data;
            this.settings = settings;
            this.fields = fields;
            this.dataSet = {
                "Result": "OK",
                "Records": this.data ? JSON.parse(this.data) : []
            };
            this.items = this.dataSet["Records"];
            this.generateId = makeIdCounter(findMaxInArray(this.dataSet["Records"], "id") + 1);
            this.dataHiddenInput = $(this.settings["hidden-input"]);
        }

        DynamicItemList.RESULT_OK = {"Result": "OK"};
        DynamicItemList.RESULT_ERROR = {"Result": "Error", "Message": "Error occurred"};
        DynamicItemList.prototype.fetchItemsList = function (postData, jtParams) {
            return this.dataSet;
        };
        DynamicItemList.prototype.createItem = function (item) {
            item = parseQueryString(item);
            item.id = this.generateId();
            this.items.push(item);
            return {
                "Result": "OK",
                "Record": item
            }
        };
        DynamicItemList.prototype.setupTable = function () {
            $(this.settings["table-container"]).jtable({
                title: this.settings['title'],
                actions: this,
                fields: this.fields
            });
        };
        DynamicItemList.prototype.load = function () {
            $(this.settings['table-container']).jtable('load');
        };
        DynamicItemList.prototype.submit = function () {
            this.dataHiddenInput.val(JSON.stringify(this.dataSet["Records"]));
        };
        DynamicItemList.prototype.removeItem = function (postData) {
            this.items = removeFromArrayByPropertyValue(this.items, "id", postData.id);
            this.dataSet["Records"] = this.items;
            this.generateId = makeIdCounter(findMaxInArray(this.dataSet["Records"], "id") + 1);
            return DynamicItemList.RESULT_OK;
        };
        DynamicItemList.prototype.updateItem = function (postData) {
            postData = parseQueryString(postData);
            var indexObjToUpdate = findIndexOfObjByPropertyValue(this.items, "id", postData.id);
            if (indexObjToUpdate >= 0) {
                this.items[indexObjToUpdate] = postData;
                return DynamicItemList.RESULT_OK;
            }
            else {
                return DynamicItemList.RESULT_ERROR;
            }

        };

【问题讨论】:

  • 原型的重点是方法是共享的,需要在方法体内使用this吗?!您只能在实际已经拥有实例的构造函数中使用 _self 方法。
  • 是的,你是对的,这是行不通的,这只是我尝试解决的一个例子,我解释了为什么这行不通,我正在寻找其他解决方案。所以我问了这个问题。
  • @chsdk 如您所见,我已经使用此链接的方法,但问题出在代码的其他部分。

标签: javascript jquery class design-patterns prototype-programming


【解决方案1】:

您将函数直接分配给原型。 DynamicItemList.prototype= 通常是DynamicItemList.prototype.somefunc= 的形式

【讨论】:

  • 是的,但是正如你所看到的,这个函数是自执行的,并返回包含一些其他函数的对象本身。我这样做是因为私有方法。是否可以像我一样保持方法私有并只公开特定部分,但让它工作)
【解决方案2】:

感谢大家的帮助,我才发现问题出在哪里。

至于最后一个版本,方法公开为公开。 有问题的部分是

   $(this.settings["table-container"]).jtable({
                    title: this.settings['title'],
                    actions: {
                        listAction: this.fetchItemsList,
                        createAction: this.createItem,
                        updateAction: this.updateItem,
                        deleteAction: this.removeItem
                    },
                    fields: this.fields
                });
            };

这里创建了一个新对象,它不知道创建它的对象的变量。

如上所示,我已将代码更改为以下内容。

  $(this.settings["table-container"]).jtable({
                title: this.settings['title'],
                actions: this,
                fields: this.fields
            });

现在它就像一个魅力。如果这种方法有缺点,请告诉我。 我的问题最初是在这部分,保持方法私有没有任何意义,因为我的对象被另一个库使用。

谢谢大家。

【讨论】:

    【解决方案3】:

    您需要使您的原型方法使用this 关键字(以便它们动态接收它们被调用的实例),但您需要将bind the instance in the callbacks 传递给jtable

    DynamicItemList.prototype.setupTable = function () {
        var self = this;
        function fetchItemsList(postData, jtParams) {
            return self.dataSet;
        }
        function createItem(item) {
            item = parseQueryString(item);
            item.id = self.generateId();
            self.items.push(item);
            return {
                "Result": "OK",
                "Record": item
            };
        }
        … // other callbacks
    
        $(this.settings["table-container"]).jtable({
            title: this.settings['title'],
            actions: {
                listAction: fetchItemsList,
                createAction: createItem,
                updateAction: updateItem,
                deleteAction: removeItem
            },
            fields: this.fields
        });
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2013-07-17
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      相关资源
      最近更新 更多