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)
Related
I once again stumbled over a behavior in Javascript that I don't understand. I need to update properties of an object as soon as a variable outside of the object is changed. The external variable is referenced in the object properties so I thought all I had to do is to change the variable externally and automatically have the property values changed.
Here's a simplified version of what the code looks like:
var serverPath = "123/";
var GetCurrentProductionApiConfig = {
URL: {
GetStart: serverPath + 'GetCurrentProduction?returnValue=start&',
GetEnd: serverPath + 'GetCurrentProduction?returnValue=end&',
Get: serverPath + 'GetCurrentProduction?returnValue=start&'
}
};
serverPath = "456/";
console.log(GetCurrentProductionApiConfig.URL.GetStart);
This will result in:
123/GetCurrentProduction?returnValue=start&
Is it because the variable has been copied (passed by value) rather than having a pointer on it (passed by reference)? And which way would be the correct one to update the properties?
Everything in JavaScript is pass by value however, it happens that the value of an object is its reference. However, the important thing here is that for primitives, will not get changes when a referenced variable changes:
var a = "world";
var obj = {
b: "hello" + a //evaluated once
}
a = "universe"; //does not modify obj.b which references a
console.log(obj.b); //helloworld
In order to have a dynamically evaluated string, you need to call a function or a method:
var a = "world";
var obj = {
b: function() {
return "hello" + a //evaluated every time the function is executed
}
}
console.log(obj.b()); //helloworld
a = "universe"; //will influence obj.b
console.log(obj.b()); //hellouniverse
However, that looks a bit "dirty" since it forces the caller to know to evaluate the property every time. It can also introduce inconsistency if some properties are plain strings, others functions and it's especially annoying if a property has to change from one to the other - you need to modify every place that calls this code to change, say, obj.c to obj.c().
Instead, using ES6+ you can define a getter for a property that will do the same as before but will hide the function call, so any time you read a property you actually evaluate code to return the result:
var a = "world";
var obj = {
c: "plain property"
}
Object.defineProperty(obj, 'b', {
get: function() {
return "hello" + a //evaluated every time the property is read
}
});
console.log(obj.b); //helloworld
a = "universe"; //will influence obj.b
console.log(obj.b); //hellouniverse
console.log(obj.c); //plain property
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I have a normal object in javascript, contenting functions and values.
This is my example object:
var MyObject = {
myData: 1,
a: function() {},
b: function() {}
}
Now in the function a there is some logic that fire on it, but it should change even the value of myData property.
But when i try get it from the method b, that value come as an undefined value, instead of the value changed.
I created a JsFiddle with a small example of the behaviour of the my object. I realized that it how Javascript behave, but I didn't understand why.
The issue is because this within the click handlers refers to the element which was clicked, not the object the handler functions are members of. You need to cache this:
a: function () {
var self = this;
$('.setValue').click(function() {
self.myData = 2;
});
},
b: function () {
var self = this;
$('.getValue').click(function() {
alert(self.myData);
});
}
Updated fiddle
In JavaScript, each function has its own this argument. In your case, you want to access the outer function's this variable so you should do something like this:
var that = this;
Here is the updated jsfiddle:
http://jsfiddle.net/xaaLQ/5/
This question already has answers here:
dynamically call local function in javascript
(5 answers)
Closed 8 years ago.
I'm having a difficulty calling a function inside of another function when its name is in a variable:
var obj = {}
obj.f = function() {
var inner = {
a: function() {
function b() {
alert('got it!');
}
b(); // WORKS AS EXPECTED
x = 'b';
[x](); // DOESN'T WORK, NEITHER this[x]() window[x](), etc.
}
}
inner.a();
}
obj.f();
I tried prefixing [x]() with different scope paths but so far w/o success. Searching existing answers did not turn up anything. It works with this[x]() if b() is placed directly inside object inner. I would like to keep b() as a function inside function a() because of variable scope in function a(), otherwise I would need to pass many parameters to b().
////
Re duplicate question: Quentin provided a more elegant answer in this thread imo.
There is no sensible way of accessing an arbitrary variable using a string matching the name of the variable. (For a very poor way to do so, see eval).
[x](); // DOESN'T WORK
You're trying to call an array as a function
NEITHER this[x]()
The function isn't a property of the inner object.
window[x](), etc.
Since it isn't a global, it isn't a property of the window object either.
If you need to call a function based on the value of a string variable, then organise your functions in an object and access them from that.
function b() {
alert('got it!');
}
var myFunctions = {
b: b
};
x = 'b';
myFunctions[x]();
Try this. Currently you are assigning string to variable x, instead of a function variable.
x = b;
x();
The problem is with your assignment
use x = b instead of x = 'b' to assign the function object as the latter just assigns the string into x.
Once you fix your assignment you can invoke the function as
x();
a.x();
a[x]();
etc.
You should make array for the function and then access using name in your variable as follow:
var obj = {}
obj.f = function() {
var inner = {
a: function() {
// set up the possible functions:
var myFuncs = {
b: function b() {alert('got it!');}
};
//b(); // WORKS AS EXPECTED --> commented this code
x = 'b';
myFuncs[x]();
}
}
inner.a();
}
The function declaration b will be captured in the closure of the anonymous function expression assigned as a.
When var is used in a closure, there is no (available in JavaScript) Object which gets assigned a property similar to what happens with window in the Global Scope.
Writing a function declaration effectively vars the name of the function.
If you really want to access a variable (i.e. b) by String, you will either need to create an Object which holds b similar to what you've done for a, or (and possibly dangerously) rely on an eval to convert "b" to b.
If you can't create the whole Object ahead-of-time, you can use this format
/* in (higher?) scope */
var fnRef = {};
// now when you
function b() {/* define as desired */}
// also keep a ref.
fnRef['b'] = b;
// fnRef['b']() will work **after this line**
let's say your code is like this:
//instead of x = 'b'
x = function(){}
then your solution could be like this:
var obj = {}
obj.f = function() {
var inner = {
a: function() {
function b() {
alert('got it!');
}
b(); // WORKS AS EXPECTED
//you can define it as a variable
var x = function(){};
//and call it like this
x();
//or define it like this
this[x] = function(){};
//and call it like this
this[x]();
//but you are creating an array [x] which is not a function
//and you are trying to call an array????
[x](); // DOESN'T WORK, NEITHER this[x]() window[x](), etc.
}
}
inner.a();
}
obj.f();
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
detect variable change in javascript
How can i found out that my variable has changed?
I have an event that performed every time when my variable is for example == 1, i want it to perfome only when my variable changes.
You can do that via a property setter, which is a newly-standardized part of the language (new as of the ECMAScript5 specification). That will only work for a property defined with a setter on an object, not with any old variable or property.
Here's an example of an object with a foo property with both a getter and a setter:
var obj = {};
Object.defineProperty(obj, "foo", (function(){
var value = 42;
function fooGet() {
display("Getting: " + value);
return value;
}
function fooSet(newValue) {
display("Setting: " + newValue);
value = newValue;
}
return {
get: fooGet,
set: fooSet
};
})());
Live example, but only works on browsers with support for ECMAScript5 properties, which I think is just Google Chrome at the moment
Or of course, just directly use getter and setter functions rather than properties. :-)
Simple: Don't use a primitive variable but an object which has a "setter" method to change the value. In the setter, you can call additional code.
You can't do this with primitives. The only way it would be possible is if you encapsulated the variable in an object, and added some custom events to this object.
#T.J. I think #Aaron is suggesting an object that does something like this:
var myVar = new Watched(1, function (newValue) { alert(newValue) });
myVar.add(2); // alert(3);
myVar.add(10); // alert(13)
Where Watched maintains an internal value that is updated by methods, which fire a callback to say they have updated.
EDITED:
Ok maybe not what #Aaron was thinking:)
I had something very simple like this in mind:
function Watched (initVal, cb) {
var value = initVal;
function add (val) {
value += val;
cb(value);
}
// return public methods
return { add: add };
}
You could use the setInterval method to periodically check the variable's value and do your stuff if it's what you want.
It's not a nice solution, though. The other suggestions are better.
http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/
EDIT:
var myVar = 0;
var intervalId = setInterval('checkVariable(myVar);', 3000);
function checkVariable(theVar) {
if (theVar == 1) {
alert('Variable is 1.');
}
}
That will execute checkVariable(myVar) every 3 seconds.