Как добавить приватную переменную в этот фрагмент литерала объекта Javascript?

Обнаружено это в MDC, но как если бы я хотел добавить приватную переменную в

var dataset = {
    tables:{
        customers:{
            cols:[ /*here*/ ],
            rows:[ /*here*/ ]
        },
        orders:{
            cols:[ /*here*/ ],
            rows:[ /*here*/ ]
        }
    },
    relations:{
        0:{
            parent:'customers', 
            child:'orders', 
            keyparent:'custid', 
            keychild:'orderid',
            onetomany:true
        }
    }
}

Как я понимаю ООП в Javascript, у меня будет доступ к dataset.tables.customers.cols [0], если такой элемент существует.
Но если бы я хотел разместить частную переменную в клиентах, что бы это выглядело?
Добавление var index = 0; приводит к ошибке выполнения.

Ответы

Ответ 1

Вы не можете иметь переменные "private" без задействованной функции. Функции - это единственный способ ввести новую область в javascript.

Но никогда не бойтесь, вы можете добавить функции в нужное место, чтобы получить такую ​​функциональность с вашим объектом.

var dataset = {
  tables: {
    customers:(function(){
      var privateVar = 'foo';
      return { 
        cols:[ /*here*/ ],
        rows:[ /*here*/ ]
      }
    }()),
    orders:{
      cols:[ /*here*/ ],
      rows:[ /*here*/ ]
    }
  },
  relations: [{
    parent:'customers', 
    child:'orders', 
    keyparent:'custid', 
    keychild:'orderid',
    onetomany:true
  }]
};

Но это не принесет нам многого. Это по большей части всего лишь куча литеральных объектов. Эти типы переменных "private" имеют нулевое значение, так как нет методов - ничего, что бы на самом деле не читало или иным образом не использовало переменные в области, которую мы создали, добавив функцию (закрытие).

Но если бы у нас был метод, который действительно мог бы стать полезным.

var dataset = {
  tables: {
    customers:(function(){
      var privateVar = 'foo';
      return { 
        cols:[ /*here*/ ],
        rows:[ /*here*/ ],
        getPrivateVar: function()
        {
          return privateVar;
        }
      };
    }()),
    orders:{
      cols:[ /*here*/ ],
      rows:[ /*here*/ ]
    }
  },
  relations: [{
    parent:'customers', 
    child:'orders', 
    keyparent:'custid', 
    keychild:'orderid',
    onetomany:true
  }]
};

alert( dataset.tables.customers.getPrivateVar() );

Ответ 2

В JavaScript не хватает средств контроля доступа, которые вы получаете на более жестких языках. Вы можете имитировать приватный доступ к данным объектов с помощью закрытий, но ваш пример - это объектный литерал - простая структура данных, а не построенный объект.

Скорее зависит от того, что вы хотите сделать с объектом. Обычный метод для членов 'private' означает, что они доступны только для функций-членов и требуют, чтобы вы использовали конструктор для создания объекта. Литеральный синтаксис используется для структур данных или легких объектов с общедоступными данными и функциями.

Проблема с использованием шаблона закрытого закрытия заключается в том, что поля внутри литерала находятся в общедоступной области, но конфиденциальность, заданная закрытием, связана с тем, что переменная определена в функции, поэтому локально локализована. Вы можете либо создать функцию, которая клонирует литерал и добавляет частные поля, либо добавляет общедоступное поле с частными данными. Вы также можете добавлять закрытие в качестве членов, поэтому создавайте частные поля, которые являются частным методом, а не частным частным.

dataset = {
    secretCounter: ( 
      function () {
      var c = 0;
      return function () { return ++c; }
    })(),      
   ...

Итак, dataset.secretCounter() имеет переменную c, которая является частной только для этой функции.

Ответ 3

Частные переменные в javascript выполняются с использованием ключевого слова var внутри закрытия. Доступ к нему могут получить только привилегированные методы и атрибуты. Вот как это сделать:

function dataset()
{
var private_stuff = 10; // private
this.foo = new function() { alert(private_stuff); } // priviliged
return {
    tables:{
        customers:{
                cols:[  ],
                rows:[  ]
        },
        orders:{
                cols:[  ],
                rows:[  ]
        }
    },
    relations:{
        0:{
                parent:'customers', 
                child:'orders', 
                keyparent:'custid', 
                keychild:'orderid',
                onetomany:true
        }
    }
}; // public
}

var d = new dataset;
alert(d.foo());