私有和公共变量到骨干视图

时间:2011-09-27 21:02:11

标签: javascript backbone.js private

在骨干视图中,您可以将私有变量和公众放在哪里。

现在我有这样的事情:

myView = Backbone.View.extend({

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

});

我尝试在initialize方法之前添加var myPrivate,但它引发了错误。只在视图中使用的私有变量在哪里?

9 个答案:

答案 0 :(得分:19)

我建议你使用initialize方法作为围绕所有其他方法的闭包。我认为这将使您的行为更符合我们在C ++和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;
        }
    };
  }
});

答案 1 :(得分:11)

在一个自我调用的匿名函数中包装它:

(function() {
    var myPrivate = 1;

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

})();

编辑:正如下面kaustubh's comment中所指出的,上面的示例创建了一个在实例之间共享的私有变量。您可以创建一种 protected 变量,即可以由View的其他实例读取的实例级变量。为每个实例提供唯一的公共ID,并将实例变量存储在“private static”变量中。然后通过实例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)
        }
    });
})();

或者,您可以在不使用公共ID的情况下执行此操作,但它会变得更复杂:

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

我正在努力想出一种存储真正私有变量的方法。如果灵感来袭,我会回复。

答案 2 :(得分:1)

而不是直接将对象插入到extend函数中,如何创建一个闭包并从该闭包返回一个对象到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);
    }
  };

} ());

我没试过这个,因为我现在没有可用的Backbone安装。

答案 3 :(得分:0)

gilly3的解决方案可能是最好的答案,虽然它在技术上不是创建/使用私有变量,因为同一个闭包的其他实例可以访问它(你可能并不关心开发团队的其他成员滥用它特权,但它可能会发生。)

如果你想在不使用gilly3方法的情况下使用私有变量,Near Privman的答案似乎是唯一真正的解决方案,因为Douglas Crockford解释了如何在这里创建私有变量:http://javascript.crockford.com/private.html

这会增加额外的javascript处理时间,因为它无法使用原型继承,并且每次都会使用资源来重新创建函数。

但是,如果每次创建的闭包非常小或者创建新实例的次数很少,则这可能不是一个非常明显的问题。为了尝试并充分利用这两个方面,您可以将使用私有变量(via delegation 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不是全局变量/函数。

答案 4 :(得分:0)

我很喜欢在接近Privman的答案,直到我遇到了一个超越&#34;超级&#34;的问题。方法。由于在构造Backbone对象之前不会调用initialize(),所以在需要时(如果需要在调用initialize()之前)可能不会发生覆盖。 / p>

特别是,这可能是parse()的问题。 (对于视图来说不是问题,但对于集合和模型来说肯定不是。)鉴于此设置:

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()都可以解决这个问题并且比使用已经具有指定目的的函数(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);

不幸的是,这与&#34;私人&#34;有同样的问题。变量在类的所有实例中共享,gilly3和Near Privman的答案都是如此。很想听到让私有变量成为可能的非尴尬方式,但也许我应该放弃并认识到我现在正在编写JavaScript,而不是Java / AS3 / C ++。

答案 5 :(得分:0)

你可以试试这个:

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

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

答案 6 :(得分:0)

添加“私有”变量的标准Backbone方法是将它们声明为带有下划线“_”的属性。它们并非真正私密,但开发人员会意识到它们并不是公开使用的。

事实上,这是Backbone如何存储自己的私有变量。

答案 7 :(得分:0)

在使用Broserify.js与Backbone(以及任何上述中型项目)的上下文中,我找到了以下方式来获得私有变量和函数:

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

答案 8 :(得分:-2)

使用“这个”?


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