The correct way to reference Javascript objects inside objects

I'm new to JavaScript, and I'm not very sure about the following legacy knockout and JS code that is used in my application:

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:

 function FbPicturesVM() { ...... some code .... } 

My question is:

  • Will each call to FbPicturesObj.fbPicturesVM create a new instance of fbPicturesVM in memory?
  • Are calls to ko.applyBindings ? (in terms of code optimization)

Thank you very much.

+5
source share
3 answers

File1.js contains the definition of a JavaScript object, or rather, the creation of a literal object.

Within each pair of propertyName: value , an initialization of a new property is declared, so that the code is run only once when the object is created. For example, fbPicturesVM: new FbPicturesVM()

The properties of JavaScript objects can be functions, such as: initialize: function () {...}, In this case, whenever you run FbPicturesObj .initialize , this function will be launched.

Calls to ko.applyBindings are correct. This method expects the viewmodel and optional DOM element to become the second parameter. The jQuery expression (not exactly) is an array of the selected DOM elements, so this $("#fb-album-photos")[0] extracts the first DOM element from the jQuery expression if ko.applyBindings is required.

NOTE. As you suspect, the way to determine the model is not the best, to say the least. You can use the drop-down module template, which simplifies the work.

Module template output

In a 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 

SPECIFY Expression with Instant Calling Function (IIFE) pattern .

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

This template defines an anonymous function that returns something. () at the end starts it, so the value is returned and stored in value ;

I recommend this patter because it is extremely easy to use and little error prone. Classic prototype inheritance, constructor, etc. Much harder to work.

You can easily convert this to a factory view model (something similar to a constructor, but not like a js constructor) by removing the - () call at the end - and saving the funcion definition so you can call it again.

 var factory = function() {/*return something*/}; var vm1 = factory(); var vm2 = factory(); 
+2
source

The constructor for FbPicturesVM runs only when the FbPicturesObj object is FbPicturesObj (in your example, this will only be when the script is included in the page). So, from a memory point of view, you only have one instance, and you then pass references to it (JS passes objects by reference basically).

I don’t know, the knockout is very good, but nothing is syntactically wrong, and the transfer of the object and the element sounds about the right to bind the code.

0
source

This question needs to be shared because the first question is not knockout related and is more about how object literals are related to object instances.

So, for question 1, the answer is no, because FbPicturesObj saves the created property, 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 always refer to the same instance, because it is stored in the people object.

0
source

Source: https://habr.com/ru/post/1238373/


All Articles