2011-09-27 68 views
12

在骨干视图中,您将在哪里放置私有变量和公共。骨干视图中的私有和公共变量

现在,我有这样的事情:

myView = Backbone.View.extend({ 

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

}); 

我试过初始化方法之前加入var myPrivate但它扔了一个错误。在视图中只使用私有变量的地方会去哪里?

+0

你能解释一下你为什么正试图做到这一点?没有一个真正的直接解决方案。 – Gazler

+0

没有太多解释appart从如何添加一个私人财产的视图。示例var myPrivate =“私有财产”,但它应该可用于整个视图,就像this.myPublic一样。除this.myPublic可以从视图实例访问。 myPrivate只能从视图方法本身访问 – Chapsterj

+1

看到这个答案: http:// stackoverflow。com/questions/8924961/private-like-properties-in-models-or-views-of-backbone-js –

回答

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指出的那样,上面的例子中创建一个实例之间共享的私有变量。您可以创建一种受保护的变量,即可以由View的其他实例读取的实例级变量。为每个实例提供一个唯一的公共ID并将实例变量存储在“私有静态”变量中。然后,通过实例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) 
     } 
    }); 
})(); 

我挣扎拿出一种存储真正的私有变量的方法。如果灵感来袭,我会回复。

+0

不要忘记最后的括号来实际使它自我调用。 – Gazler

+0

@Gazler - 很好,谢谢! – gilly3

+0

感谢Gazler,你将如何创建这个视图的一个实例。或者你将如何能够建立视图的实例 – Chapsterj

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

在使用私有变量的初始化内部添加方法时,是否每次创建对象时都会使初始化变慢? –

+1

@StalinGino是的。我不知道这是否会让人感觉放缓,但它肯定会在内存中占据更多的空间。 – pilau

-2

使用“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}) 

0

gilly3的解决方案可能是最好的答案,但它在技术上并不创建/使用私有变量,因为同其他关闭情况下,将有机会获得它(你可能是不关心的其他成员你开发团队滥用该特权,但可能会发生)。

如果你想使用私有变量,而无需使用gilly3的做法,近Privman的答案似乎是唯一真正的解决方案,道格拉斯克罗克福德解释了如何在这里创建私有变量: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不是全局变量/功能。

1

不是直接将对象插入到扩展函数中,而是如何创建闭包并从该闭包返回对象到扩展函数?

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

}()); 

我没试过,因为我没有骨干安装可用的现在。

+0

我现在认识到这些私有变量将被这个视图的多个实例共享。对此的修复将是: _privates = {}; _privates [this.cid] = {}; //用于存储特定对象的私人东西的对象(通过cid)。 – jgroenen

0

我很喜欢Privman的答案,直到遇到覆盖“super”方法的问题。由于initialize()在通过构建Backbone对象的某种方式之前不会被调用,所以在需要的时候覆盖可能不会发生(如果需要在调用initialize()之前)。

特别是,这可能是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())功能吸尘器完成双重任务作为一个封闭定义休息的类。

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

不幸的是,这与跨类的所有实例所共享的“私人”变量,两者都做gilly3和近Privman的回答同样的问题。希望听到一个非尴尬的方法来使私有变量成为可能,但也许我应该放弃并认识到我现在正在编写JavaScript,而不是Java/AS3/C++。

0

你可以试试这个:

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

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

加入“私有”变量的标准骨干的方式是他们之前他们宣布与下划线属性“_”。他们并不是真正的私人,但开发人员会意识到他们并不是公开使用的。

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

0

在使用Broserify.js与骨干网的情况下(与任何真正的中等以上的项目),我发现下面的办法有私人VAR和功能:

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