简体   繁体   English

在对象中引用Javascript对象的正确方法

[英]Right way of referencing Javascript Objects inside Objects

I'm a newbie to JavaScript, and I'm not very sure about the following legacy knockout and JS code which is being used in my app: 我是JavaScript的新手,我不太确定在我的应用程序中使用的以下遗留淘汰赛和JS代码:

file1.js: file1.js:

var FbPicturesObj = {
    fbPicturesVM: new FbPicturesVM(),
    initialize: function () {
        ko.applyBindings(FbPicturesObj.fbPicturesVM, $("#fb-albums")[0]);
        ko.applyBindings(FbPicturesObj.fbPicturesVM, $("#fb-album-photos")[0]);
    },
    Reset: function Reset() {
        FbPicturesObj.fbPicturesVM.albums([]);
        FbPicturesObj.fbPicturesVM.photos([]);
    }
}

file2.js: file2.js:

function FbPicturesVM() { 

...... some code ....
 }

My question are: 我的问题是:

  1. Does each call to FbPicturesObj.fbPicturesVM will create a new instance of fbPicturesVM in memory? 每次调用FbPicturesObj.fbPicturesVM都会在内存中创建FbPicturesObj.fbPicturesVM的新实例吗?
  2. Are the ko.applyBindings calls are written correctly? ko.applyBindings调用是否正确写入? (in terms of code optimization) (在代码优化方面)

Thanks a lot. 非常感谢。

File1.js contains a definition of a JavaScript object, more exactly a "literal object creation". File1.js包含JavaScript对象的定义,更确切地说是“文字对象创建”。

Inside it, each propertyName: value pair declares an initializes a new property, so that code is run only once, when creating the object. 在其中,每个propertyName: value对声明一个初始化一个新属性,因此在创建对象时代码只运行一次。 For example fbPicturesVM: new FbPicturesVM() 例如fbPicturesVM: new FbPicturesVM()

Properties of JavaScript objects can be functions, like this: initialize: function () {...}, . JavaScript对象的属性可以是函数,如下所示: initialize: function () {...}, . In this case, whenever you run FbPicturesObj .initialize this function will be run. 在这种情况下,无论何时运行FbPicturesObj .initialize都将运行此函数。

The calls to ko.applyBindings are correct. ko.applyBindings的调用是正确的。 This method expects the viewmodel object and an optional DOM element as the second parameter. 此方法需要viewmodel对象和可选的DOM元素作为第二个参数。 A jQuery expression is (not exactly) an array of selected DOM elements, so this $("#fb-album-photos")[0] extracts the first DOM element of the jQuery expression, as needed by ko.applyBindings . jQuery表达式(不完全是)所选DOM元素的数组,因此这个$("#fb-album-photos")[0]根据ko.applyBindings需要提取jQuery表达式的第一个DOM元素。

NOTE: as you suspect, the way of defining the model is not the best possible, to say the least. 注意:正如您所怀疑的那样,至少可以说,定义模型的方式并不是最好的。 You can use the Revealing Module Pattern, which makes things much easier. 您可以使用Revealing Module Pattern,这样可以更轻松。

Revealing Module Pattern 揭示模块模式

In few words: 简而言之:

var vm = (function() { // declare a function
   // create variables and functions
   var name = ko.observable();
   var age = ko.observable();
   var _privateVar = 'Yuhu'; // won't be revealed
   var incAge = function() {
      age = age + 1;
   };
   // reveal only what you want, by returning it in an object
   return {
     name: name,
     age: age,
     incAge: incAge
     // note that _privateVar is not exposed, but could be
   }
})(); // This invokes the function, so that it return the model

NOTE the pattern Immediately-Invoked Function Expression (IIFE) . 注意模式立即调用函数表达式(IIFE)

var value = (function() {/*return something*/})(); 

This pattern defines an anonymous function, that returns something. 此模式定义了一个匿名函数,它返回一些东西。 The () at the end runs it, so that the value is returned, and stored in value ; 最后的()运行它,以便返回值并存储在value ;

I recommend this patter because it's extremely easy to use and little error prone. 我推荐这种模式,因为它非常易于使用且容易出错。 Classical prototypal inheritance, constructor, and things like that are much harder to work with. 经典的原型继承,构造函数和类似的东西更难以使用。

You can easyly convert this in a view model factory (something similar to a constructor, but not eactly a js constructor) by removing the invocation - () at the end - and storing the funcion definition, so that you can call it repeatedly. 您可以通过删除最后的调用 - ()并存储函数定义,在视图模型工厂(类似于构造函数,但不是js构造函数)中轻松转换它,以便您可以重复调用它。

var factory = function() {/*return something*/}; 

var vm1 = factory();
var vm2 = factory();

The constructor for FbPicturesVM only invokes when the FbPicturesObj object is instantiated (in your example, this will just be when the script is included in the page). FbPicturesVM的构造FbPicturesVM仅在实例化FbPicturesObj对象时调用(在您的示例中,这将是脚本包含在页面中时)。 So, in terms of memory, you have just the one instance and you're then passing references to it (JS passes objects by reference mostly). 因此,就内存而言,您只有一个实例,然后您将对它的引用传递给它(JS主要通过引用传递对象)。

I dont know knockout very well but theres nothing syntactically wrong and passing an object and an element sounds about right for binding code. 我不知道淘汰赛很好但是没有语法错误,传递一个对象和一个元素听起来正确的绑定代码。

This question should be split up, because the first question is unrelated to Knockout, and more to do with how object literals are associated with instantiated objects. 这个问题应该分开,因为第一个问题与Knockout无关,更多的是与对象文字如何与实例化对象相关联。

So for question 1, the answer is "no" because FbPicturesObj saves the instantiated property, FbPicturesObj.fbPicturesVM 因此对于问题1,答案是“否”,因为FbPicturesObj保存了实例化的属性FbPicturesObj.fbPicturesVM

Consider the following: 考虑以下:

 var Person = function(name) { this.name = name } Person.prototype.sayName = function() { return this.name } var people = { fred : new Person('fred') } console.log(people.fred.sayName()); // returns 'Fred' var people = { fred : new Person('jane') } console.log(people.fred.sayName()) // returns 'jane' and not 'fred' var people = { fred : new Person('fred'), jane : new Person('jane') } console.log(people.fred.sayName()) // returns 'fred' console.log(people.jane.sayName()) // returns 'jane' 

In this case each call to 'person.fred' will refer to the same instance always, because its saved to the people object. 在这种情况下,对'person.fred'的每次调用都将始终引用相同的实例,因为它保存到people对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM