This line is at the top of a JavaScript file in a project at school. Can someone tell me what exactly it does?
var Tele = { 'Forms': {}, 'Form': {} };
It is then followed with three functions like this that all contain more functions as exampled below.
FormsView.js
Tele.Forms.View = new function (){
this.SetRequestTitle = function (title) {
if (el.length == 0) {
setTimeout(function () { Tele.Forms.View.SetRequestTitle(title); }, 100);
return;
}
$('#FormTitleBarSubMenuText').html(title);
document.title = title;
};
....
....
};
Then there is a second JavaScript file FormView.js that only contains this
Tele.Form.View = new function () {
this.Initialize = function (data) {
Tele.Forms.View.SetRequestTitle('Approval Request');
};
};
I am new to JavaScript and scripting in general so I am just trying to figure out how things work.
I understand what is happening inside the functions, just not what is tying it all together. Thanks!
That line simply declares a variable:
var Tele; // Declare a variable with the identifier Tele
And assigns an object literal to it:
Tele = {} // Empty object literal
The object literal has 2 properties, Forms and Form, the value of each of which is another object literal:
Tele = { 'Forms': {}, 'Form': {} } // Object literal with 2 properties
Later on, these properties are referred to, and further properties are added to their values (their values are object literals, so you can add properties to them as follows):
Tele.Form.View = new function () { // Add a View property to Tele.Form
// ...
};
var Tele = { 'Forms': {}, 'Form': {} };
This declares a Tele object with two empty objects inside (Forms and Form). The other two snippets assign properties to those objects (Tele.Forms.View and Tele.Form.View).
That is a JavaScript object. It contained two properties Forms and Form that are currently empty when created.
To the first property, Forms, another property is assigned to it, which is the function (the function is usually called a closure).
To the second property, Form, another property is assigned to it as well, which is also a function.
To call out the first function, you simply call
Tele.Forms.View();
and to call the second,
Tele.Form.View();
Hope the explanation is clear and it helps.
Related
This question already has answers here:
Javascript - How change object properties without reassign them
(4 answers)
Closed 3 years ago.
I am using angularJS, and have the following controller variables:
cont.flag = 0;
cont.obj = {objFlag: cont.flag, objFunction: cont.func};
cont.func = function() {
// do stuff
}
The cont.flag variable is bound to user input in the HTML. So when that value changes I want the objFlag to update which it is not currently doing. In addition the objFunction value seems to always be undefined. Is this because cont.obj is declared above cont.func?
EDIT: If it wasn't clear, the cont.flag variable is correctly being updated by the user input, it's just the pointer to cont.flag in my obj which is not updating. Also, objFunction is not getting populated with the function I pass it.
Here is a bit more information that I provided in a comment about why I have these variables in an object instead of manipulating them directly: So I have a series of functions that I want to chain together, but I want to control which functions get run. So I have an obj for each function: the objFlag which says whether the function should be added to the chain, and objFunction which is the actual function to be run. I wanted a way of associating the objFlag with the objFunction it goes with
The reason why objFlag is not change along with cont.flag has nothing to do with Angular. This is a native Javascript behavior.
This statement:
cont.obj = {objFlag: cont.flag, objFunction: cont.func};
only assigns an initial cont.flag value to objFlag and there is no ongoing link between objFlag and cont.flag
This is already explained
Javascript - How change object properties without reassign them
object property to dynamically change with the value of assigned variable
Let us think your code in other way
cont.flag = 0;
cont.obj = {objFlag: cont.flag, objFunction: cont.func};
cont.func = function() {}
which is equivalent to
var cont = {
flag: 0,
obj: {objFlag: cont.flag, objFunction: cont.func},
func: function() {}
}
console.log(cont.obj);
You can see the result, undefined cont here (Cannot read property 'flag' of undefined"). we can not access variable into another variable within same object.
So, you will think to use this here
var cont = {
flag: 0,
obj: {objFlag: this.flag, objFunction: this.func},
func: function() {}
}
console.log(cont.obj);
Again you will get undefined values because we can not access object elements with another variable. But we can use function to access them. So last option is to use a getter function for obj to return json with data of other variable into a variable. (in self-referencing json object)
var cont = {
flag: 0,
get obj() {return {objFlag: cont.flag, objFunction: cont.func}},
/*or*/
/* get obj() {return {objFlag: this.flag, objFunction: this.func}},*/
func: function() {}
}
console.log("Before change", cont.obj);
//change
cont.flag = 10;
console.log("After change", cont.obj);
UPDATE
Now, combining your case with above explanation where cont is controller's reference, how you can add a getter property in angular controller.
Object.defineProperty method is what you need. So your final code will be:
cont.flag = 0;
Object.defineProperty(cont, 'obj', {
get: function() {
return {objFlag: cont.flag, objFunction: cont.func}
}
});
cont.func = function() {}
// you can access obj property to see the values
console.log(cont.obj)
While reading other people's source code and various articles over the web, I found that when different people use "object-oriented-style" programming in JavaScript, they often do it quite differently.
Suppose, I want to create a tiny module having 1 property and 1 function. I've seen at least 4 approaches to this task:
// Option 1
var myObject1 = {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
// Option 2
var myObject2 = function () {
return {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
}();
// Option 3
var MyObject3 = function () {
this.myProp = 1;
this.myFunc = function () { alert("myProp has value " + this.myProp); }
};
var myObject3 = new MyObject3();
// Option 4
var MyObject4 = function () { };
MyObject4.prototype.myProp = 1;
MyObject4.prototype.myFunc = function () { alert("myProp has value " + this.myProp); };
var myObject4 = new MyObject4();
All these approaches are syntactically different but seem to produce objects that can be used in the same way.
What's the semantic difference between them? Are there cases when for some reason I should choose one of these options over all the rest?
myObject1 is an object literal (singleton). Useful in cases where you want to have just one object of this type. Look at it as a static object.
myObject2 returns an object literal. So right after doing var foo = myObject2(), the variable foo will hold the result { myProp: 1, myFunc: function(){...} } with reference to the parent function that has executed. This is called a closure. This can be used to define a public API or modules, for example.
i.e.:
var foo = (function(){
var privateProp = "I am a private property";
// the object below is returned, privateProp is accessible
// only through foo.publicProp
return {
publicProp: privateProp
}
})();
The privateProp property is now accessible through foo.publicProp.
MyObject3 and MyObject4 are constructor functions. By using the new keyword before the function call, you tell JavaScript to create an instance of that object. This means that every new object created this way will inherit properties and methods from the object definition.
The difference between MyObject3 and MyObject4 is that in the case of the former, every instance of that object will have its own copy of the myProp and myFunc properties, whereas the latter will only reference those properties. That means that no matter how many instances of object MyObject4 you create, there will be only one of myProp and myFunc.
I recommend you look up on how closures, prototypal inheritance, and several object design patterns (modules, etc.) work in JavaScript.
Both 1. and 2. are pretty much identical in your example. You could make 2. make an actual difference by declaring "private" variables in the IIFE's scope, like this:
var myObject2 = function () {
var myPrivateProp = ...;
return {
getPrivateProp: function() { return myPrivateProp; }
};
}();
In general, those create a value, not something that you would call a class of values.
Instead, what 3. and 4. are doing is creating a prototype that can be then used to create more usable values out of it. Whether you actually declare the defaults on the prototype or in the constructor doesn't make much difference.
So, to sum up, 1&2 are something like a "lambda" object, without a named prototype, while 3&4 actually make the thing reusable and recreatable.
please help solve the problem.
i make 3 objects:
level:
var Level = function() {
self = this;
this.cellsObserver = new CellsObserver();
console.log('co from level ' + this.cellsObserver);
this.fieldObj = new Field();
}
field:
var Field = function() {
self = this;
this.init();
};
Field.prototype = Object.create(Level.prototype);
Field.prototype = {
init: function() {
console.log('co from field ' + self.cellsObserver);
}
}
observer:
var CellsObserver = function(){
.............
}
in result console output follow:
co from level [object Object] co from field undefined
I do not understand why in the second case output 'undefined'. because I have appointed a parent:
Field.prototype = Object.create(Level.prototype);
tl;dr: there is no field cellsObserver neither in Field or Level.prototype object. And there is no such thing as a classical 'self' in Javascript.
The long story.
When you're trying to fetch object.property, the Javascript will look at the object trying to find property, then to the object.prototype (which is another object) and so on until it get to the null prototype in the Object.prototype reference.
So, when you're calling second time the this.cellsObserver in Level constructor function, it goes like this:
this is a just new constructed object (if it called with the new keyword), and there is cellsObserver in the property list, so it'll be fetched without any deep lookup.
Then,
Field.prototype = Object.create(Level.prototype);
This only means that Field.prototype now will refer to a new object, which properties are the same as in Level.prototype in that moment.
From your code, there are no non-standard properties in Level.prototype object (you didn't provide any).
Then,
self = this;
Here you just assigning a global variable called self a reference to the just created object or window object (it depends). If you wish to store a reference to the this object, you should var: var self = this. But you should remember that this self variable could be accessed only in the scope where is was declared or in a closure.
Then,
Field.prototype = {
init: function() {
console.log('co from field ' + self.cellsObserver);
}
}
First of all, here you just override the previos instruction (Field.prototype = Object.create(Level.prototype);). If you want to extend the Field.prototype object, you could do in the Object.create call in second argument, or just by accessing a property like that: Field.prototype.init = function(){...}.
Second. The self variable could contain anything when the init function will be executed. Just use this for the current object here.
Third. Let's try to guess what will happen when this.cellsObserver get evaluated inside this init function.
The this object is referring to the Field instance, and there is no cellsObserver property there, so we move to the Field.prototype object, which is defined above ({ init: function () {...}}), there is no cellsObserver either, so we move to the Object.prototype object, which is null. Ok, our lookup is failed, this.cellsObserver is undefined.
What would be it look like if the Field.prototype = Object.create(Level.prototype) wasn't been overridden by the following code? The this object will refer to the Field instance as early. The Field.prototype is referring to the object which is copy of the Level.prototype object, and there is no cellsObserver here either. So, we look to the Object.prototype, and that's it. There is no cellsObserver in any objects except in the instances on Level class, which isn't referenced in any way in the Field instances.
You can play with that here: http://www.objectplayground.com/ by pasting this code:
var Level = function() {
this.cellsObserver = new CellsObserver();
this.fieldObj = new Field();
}
var Field = function() {
this.init();
};
Field.prototype = Object.create(Level.prototype);
Field.prototype.init = function() {};
this.field = new Field();
You are overriding the Field.prototype. Just assign to Field.prototype.init.
I am trying to create a JavaScript library of UI components that are commonly used by the projects in my group. I have the following code to define the library.
var libName = function() {
var _libName = this;
_libName.componentName = function () {
// Some Private Variables
var _componentName = function (args) {
// Construct the object...
};
_componentName.addObject = function (args) {
// Add an object...
};
_componentName.removeObject = function (args) {
// Remove an object...
};
return _componentName;
}();
return _libName;
}();
Now, when I use this in a page to create the component I call the following code.
var component = new libName.componentName(args);
It initializes just fine and creates the base component that I expect. Now I want to add some data to the component, so I call the following function.
component.addObject(someObject);
But instead of calling the function like I expect it to, it says that the component object does not have a property 'addObject'. I looked into this with the following code.
if (libName.componentName.addObject) {
console.log("libName.componentName.addObject exists"); // Logs
}
if (component.addObject) {
console.log("component.addObject exists"); // Doesn't log
}
if (component.constructor.addObject) {
console.log("component.constructor.addObject exists"); // Logs
}
So my question is what exactly is going on here? Why does an object, in this case component, not have access to the properties/functions I expect it to? Does this have something to do with the fact that I am using memoized closures to define the library? How do I make it so that an object initialized from this library has access to these properties/functions?
Use the prototype of the function to define instance methods :
_componentName.prototype.addObject = function (args) {
// Add an object...
};
_componentName.prototype.removeObject = function (args) {
// Remove an object...
};
your script doesnt work because you are calling _componentName properties , that are not passed to instances of _componentName if defined directy on the object. Remember using new mean using prototypal inheritance. Javascript doesnt have class based inheritance.
I have an object defined outside the function, in a global scope. This object is not passed into the function as an argument, but the function does modify it and return the modified object.
What I wanted to know is, if the function returns a copy of the object, or the original global object?
Also, will passing that object to the function as an argument, make a difference, since objects are passed into functions by reference?
Whenever you're returning an object, you're returning a reference to the object. Likewise, when you're passing an object, you're passing a reference. However, passing an object in as an argument can be different than just changing an object in global scope, as these examples show. This is because the reference to the object is itself passed by value.
If you're changing the members of an object, then whether you pass it in as an argument or just update the global object makes no difference. Either way, you're working with the same object.
Example 1:
var object = {foo:'original'};
function changeObject() {
object.foo = 'changed';
return object;
}
console.log(changeObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
Example 2:
var object = {foo:'original'};
function changeArgument(object) {
object.foo = 'changed';
return object;
}
console.log(changeArgument(object)); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
On the other hand, if you're overwriting the object with a new object, the change won't persist if you do it to the argument, but will persist if you do it to the global object. That's because the argument passes the reference to the object by value. Once you replace this value with a reference to a new object, you're not talking about the same object anymore.
Example 3:
var object = {foo:'original'};
function replaceObject() {
object = {foo:'changed'};
return object;
}
console.log(replaceObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}
Example 4:
var object = {foo:'original'};
function replaceArgument(object) {
object = {foo:'changed'};
return object;
}
console.log(replaceArgument(object)); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'original'}
May be late comment, but this is typical challenge in any language.
Objects created on the heap and passed around by reference opposed to primitives(by value).
I think the root of the question is shared instance versus unique one to avoid unwelcome effects.
For example we calling a function to get a template(object) for new user to add to collection or want to clear the form
on cancel event from different modules to start over. It easy to understand and easy to overlook..test cases typically
not covering all usage permutations
The sanity checklist:
Here the shared instance:
var bigo = {
usr: { name: 'steven' },
bigi: function () {
return this.usr;
}
};
var outA = bigo.bigi();
var outB = bigo.bigi();
print(outA.name); // => steven
print(outB.name); // => steven
outA.name = 'ilan'; // change value
print(outA.name); // => ilan
print(outB.name); // => ilan
Non shared instance:
var bigo = {
bigi: function () {
var user = { name: 'steven' };
return user;
}
};
var outA = bigo.bigi();
var outB = bigo.bigi();
print(outA.name); // => steven
print(outB.name); // => steven
outA.name = 'ilan'; // change value
print(outA.name); // => ilan
print(outB.name); // => steven
What I wanted to know is, if the function returns a copy of the object, or the original global object?
Effectively, you only ever deal with references to objects in JavaScript. Even var foo = {} just assigns a reference to a new object to foo.
If the object is outside the function, you don't need to 'return' it. If you modify the object within the function it will update the object itself. Then you can reference the newly updated object in other functions as needed.
From your question this is how I think your code looks (more or less):
var o = {};
function f() {
o.prop = true;
return o;
}
In this case the global variable o references an object.
When you modify o you're modify whatever o references. Hence it modifies the original object.
When you return o you're returning a reference to the original object.
Passing the object to a function results in the reference to the original object being passed. Hence any modifications will affect the original object. For example:
var o = {};
f(o);
console.log(o.prop); // true
function f(o) {
o.prop = true;
}