1

我有對象範圍的問題。從原型函數訪問對象上下文JavaScript

這裏是我的類代碼

// 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

我嘗試了不同的方法,但都沒有工作。

請建議我該如何解決這個問題。

Thx。

UPDATE

這裏是版本的所有方法的公開爲公衆。

  // 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; 
      } 

     }; 
+0

原型的全部內容是方法共享任何需要在方法體內使用'this'?!您只能在實際已經有實例的構造函數中使用'_self'方法。 – Bergi

+0

是的你是對的,這是行不通的,這只是我試圖解決的一個例子,我解釋了爲什麼這不起作用,我正在尋找其他解決方案。所以我問了這個問題。 – CROSP

+0

[JavaScript私有方法]的可能重複(http://stackoverflow.com/questions/55611/javascript-private-methods) –

回答

0

您將函數直接分配給原型。 DynamicItemList.prototype=通常情況下,這是表格DynamicItemList.prototype.somefunc=

+0

是的,但正如你所看到的,這個函數是自我執行的並且返回包含一些其他函數的對象本身。我之所以這樣做是因爲私人方法。是否有可能保持私有方法,只暴露特定的部分,就像我做的那樣,但是讓它工作) – CROSP

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 
      }); 

而現在它就像一個魅力。如果這種方法有缺點,請告訴我。 我的問題最初是在這個部分,保持私有方法沒有任何意義,因爲我的對象被另一個庫使用。

Thx everyone。

0

您需要使您的原型方法使用關鍵字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 
    }); 
};