Private and public variables to a backbone view

2019-03-24 22:21发布

In a backbone view where would you put your private variables and your public.

Right now I have something like this:

myView = Backbone.View.extend({

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

});

I tried adding a var myPrivate before the initialize method but it threw an error. Where would private variables that are only used within the view go?

9条回答
放荡不羁爱自由
2楼-- · 2019-03-24 22:31

Wrap it all up in a self-invoking anonymous function:

(function() {
    var myPrivate = 1;

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

})();

Edit: As pointed out in kaustubh's comment below, the above example creates a private variable that is shared among the instances. You could create a sort of protected variable, that is, an instance level variable that could be read by other instances of the View. Give each instance a unique public id and store instance variables in a "private static" variable. Then access the variables by instance id:

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

Or, you can do it without using a public id, but it becomes a bit more convoluted:

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

I'm struggling to come up with a way of storing truly private variables. I'll post back if inspiration strikes.

查看更多
戒情不戒烟
3楼-- · 2019-03-24 22:31

gilly3's solution may be the best answer, although it is not technically creating/using a private variable because other instances of the same closure will have access to it (you probably are not as concerned about other members of your development team misusing that privilege, but it could happen).

If you want to use private variables without using gilly3's approach, Near Privman's answer appears to be the only true solution as Douglas Crockford explains how to create private variables here: http://javascript.crockford.com/private.html

This will add additional javascript processing time since it will not be able to make use of prototypal inheritance and will be using resources to recreate the function each time.

However, this may not be a very noticeable issue if the closure you create each time is very small or if the number of times a new instance is created is minimal. In an effort to try and get the best of both worlds, you can delegate the bulk of your method that uses the private variable (via delegation pattern) to a static function that won't get recreated each time. This will leave your publicMethodThatUsesPrivateVariable method shown below smaller, which means that it should take less time to recreate each time.

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

        // ...
    });

Note that the code above should be wrapped in some kind of function as well so that _privateStaticMethod is not a global variable/function.

查看更多
地球回转人心会变
4楼-- · 2019-03-24 22:33

I suggest you use the initialize method as a closure around all other methods. I think this will give you behaviour more consistent with what we get in classical inheritance languages like C++ and 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;
        }
    };
  }
});
查看更多
贼婆χ
5楼-- · 2019-03-24 22:36

You can try this:

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

            this.getValue = function ()
            {
                console.log(_value);
            };
            this.setValue = function (value)
            {
                _value = value;
            };
        }
    });
查看更多
小情绪 Triste *
6楼-- · 2019-03-24 22:36

In the context of using Broserify.js with Backbone (and really any above medium project) I found the following way to have private vars and functions:

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);
    },
});
查看更多
做自己的国王
7楼-- · 2019-03-24 22:40

The standard Backbone way of adding "private" variables is to declare them as attributes with an underscore "_" before them. They are not really private, but developers will realize that they are not meant to be publicly used.

This, in fact, is how Backbone stores its own private variables.

查看更多
登录 后发表回答