Подтвердить что ты не робот

Частные и общедоступные переменные для представления в режиме магистрали

В представлении с базой данных, где бы вы разместили свои частные переменные и свою публикацию.

Сейчас у меня есть что-то вроде этого:

myView = Backbone.View.extend({

  initialize: function(options){
    this.myPublic = "I'm public";
  }

});

Я попробовал добавить var myPrivate до метода initialize, но он сделал ошибку. Где будут использоваться частные переменные, которые используются только в представлении?

4b9b3361

Ответ 1

Я предлагаю использовать метод initialize как закрытие всех других методов. Я думаю, что это даст вам поведение, более совместимое с тем, что мы получаем на классических языках наследования, таких как С++ и Java:

myView = Backbone.View.extend({

  initialize: function(options){
    var myPrivate = "I'm private";

    this.myPublic = "I'm public";

    this.getPrivate = function () {
      return myPrivate;
    };

    this.setPrivate = function (value) {
        if (typeof(value) === 'string') {
            myPrivate = value;
            return true;
        } else {
            return false;
        }
    };
  }
});

Ответ 2

Оберните все это в самоназывающую анонимную функцию:

(function() {
    var myPrivate = 1;

    myView = Backbone.View.extend({  
        initialize: function(options){  
            this.myPublic = "I'm public";
            myPrivate++;
        },
        render: function() {
            alert(myPrivate);
        }
    });

})();

Изменить: Как указано в комментарий kaustubh ниже, приведенный выше пример создает приватную переменную, которая является общей для экземпляров. Вы можете создать защищенную переменную, то есть переменную уровня экземпляра, которая может быть прочитана другими экземплярами представления. Дайте каждому экземпляру уникальный общедоступный идентификатор и сохраните переменные экземпляра в переменной "private static". Затем перейдите к переменным по идентификатору экземпляра:

(function() {
    var data = [];

    myView = Backbone.View.extend({  
        initialize: function(options){  
            this.myPublic = "I'm public";
            this.Id = data.length;
            data.push({});
            data[this.Id].myProtected = "abc";
        },
        render: function() {
            alert(data[this.Id].myProtected)
        }
    });
})();

Или вы можете сделать это, не используя общедоступный идентификатор, но он становится немного более запутанным:

(function() {
    var data = (function () {
        var dataValues = [];
        return function (instance) {
            for (var i = 0; i < dataValues.length; i++) {
                if (dataValues[i].instance === instance) {
                    return dataValues[i].data;
                }
            }
            var dataObject = { instance: instance, data: {} };
            dataValues.push(dataObject);
            return dataObject.data;
        };
    })();

    myView = Backbone.View.extend({
        initialize: function(options){  
            this.myPublic = "I'm public";
            data(this).myProtected = "abc";
        },
        render: function() {
            alert(data(this).myProtected)
        }
    });
})();

Я изо всех сил пытаюсь придумать способ хранения действительно частных переменных. Я отправлю обратно, если ударит вдохновение.

Ответ 3

Вместо того, чтобы вставлять объект непосредственно в функцию extend, как насчет создания замыкания и из этого закрытия возвращать объект в функцию расширения?

var myView = Backbone.View.extend(function () {

  var _myPrivateOne = 0;

  function _myPrivateStrangeSquareFunction(a) {
    return a * a + 1;
  }

  return {
    initialize: function (options) {
      _myPrivateOne = options.privateOne;
      this.myPublicOne = options.publicOne;
    },
    setPrivateOne: function (value) {
      _myPrivateOne = value;
      return _myPrivateOne;
    },
    getPrivateOne: function () {
      return _myPrivateOne;
    },
    getPrivateOneStrangelySquared: function () {
      return _myPrivateStrangeSquareFunction(_myPrivateOne);
    }
  };

} ());

Я не пробовал это, потому что у меня нет установленной базовой системы.

Ответ 4

Решение

gilly3 может быть лучшим ответом, хотя это не технически создает/использует приватную переменную, потому что другие экземпляры одного и того же закрытия будут иметь к нему доступ (вы, вероятно, не так обеспокоены тем, что другие члены вашей команды разработчиков неправильно используют это привилегия, но это может произойти).

Если вы хотите использовать частные переменные без использования подхода gilly3, то ответ "Близкий Привман" представляется единственным истинным решением, поскольку Дуглас Крокфорд объясняет, как создавать частные переменные здесь: http://javascript.crockford.com/private.html

Это добавит дополнительное время обработки JavaScript, поскольку оно не сможет использовать прототипное наследование и будет использовать ресурсы для воссоздания функции каждый раз.

Однако это может быть не очень заметной проблемой, если замыкание, которое вы создаете каждый раз, очень мало или если количество создаваемых новых экземпляров минимально. Чтобы попытаться получить лучшее из обоих миров, вы можете делегировать основную часть вашего метода, который использует приватную переменную (через делегирование pattern) к статической функции, которая не будет воссоздаваться каждый раз. Это приведет к тому, что ваш метод publicMethodThatUsesPrivateVariable будет показан ниже меньшим, а это означает, что для восстановления каждого времени требуется меньше времени.

    var _privateStaticMethod = function(privateVariableValue, methodParameter) {
        var result;

        // Execute the lengthy javascript logic here ...

        result = Math.ceil(privateVariableValue / 108);
        result += 4815162342;
        return result;
    };

    Backbone.View.extend({
        initialize: function() {
            var _privateVariable = 303;

            this.publicMethodThatUsesPrivateVariable = function(methodParameter) {
                // Only place as little logic as you can here outside of the private static method being used below
                _privateVariable += 1;

                return _privateStaticMethod(_privateVariable, methodParameter);
            };
        },

        // ...
    });

Обратите внимание, что приведенный выше код также должен быть обернут какой-то функцией, так что _privateStaticMethod не является глобальной переменной/функцией.

Ответ 5

Мне понравился ответ Прирумана, пока я не столкнулся с проблемой переопределения "супер" метода. Поскольку initialize() не вызван каким-либо образом через конструкцию объекта Backbone, переопределение может не произойти к моменту, когда это необходимо (если это необходимо до вызова initialize()).

В частности, это может быть проблемой с parse(). (Не проблема для Views, но определенно для коллекций и моделей.) С учетом этой настройки:

MyModel = Backbone.Model.extend({
    initialize: function (options) {
        this.parse = function (response, xhr) {
            // parsing logic
        };

        // public & private vars/methods here
        // and also initialize code
    }
});

MySubModel = MyModel.extend({
    initialize: function (options) {
        this.parse = function (response, xhr) {
            // override MyModel with my own parsing logic
        }

        // public & private vars/methods here
        // and initialize code here
    }
});

MySubModel.parse() никогда не будет вызываться.

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

var MyModel = {};
(function () {
    this.initialize = function (attributes, options) {
        // initialize me
    }

    this.parse = function (response, xhr) {
        // override at will
    }

    // other public & private vars/methods here
}).call(MyModel);

Backbone.Model.extend(MyModel);

К сожалению, это связано с тем, что переменные "private" разделяются во всех экземплярах класса, как и ответы gilly3 и Near Privman. Хотелось бы услышать неловкий способ сделать частные переменные возможными, но, возможно, мне следует просто отказаться от него и признать, что я пишу JavaScript сейчас, а не Java/AS3/С++.

Ответ 6

Вы можете попробовать следующее:

var Thing = Backbone.Model.extend(
    {
        constructor : function ()
        {
            var _value = "Private data!";

            this.getValue = function ()
            {
                console.log(_value);
            };
            this.setValue = function (value)
            {
                _value = value;
            };
        }
    });

Ответ 7

Стандартный базовый способ добавления переменных "private" заключается в том, чтобы объявить их как атрибуты с подчеркиванием "_" перед ними. Они не являются частными, но разработчики поймут, что они не предназначены для публичного использования.

Это, по сути, то, как Backbone хранит свои собственные частные переменные.

Ответ 8

В контексте использования Broserify.js с помощью Backbone (и действительно любого выше среднего проекта) я нашел следующий способ иметь частные vars и функции:

myView.js

'use strict';

var config     = require('../config.js'),

    private_var   = 'private variable',
    my_private_fn = function() {
        ...
    };


module.exports = Backbone.Model.extend({
    initialize: function() {
        this.my_public = 'public variable');

        console.log('This is my' + this.my_public);
        console.log('This is my' + my_private);
    },
});

Ответ 9

Использование "this"?

    initialize:function () {
        this.viewpointers = {}
    },
    render:function () {
        var self = this
        _.each(this.viewpointers, function(item){
            self.$el.find(".assigned-items").append(item.render().el)
        });
    }

добавив их. Затем они защищены по крайней мере.

    this.viewpointers[model.id] = new view({model:model})