I was trying to determine the best way to observe a variable's value and track its changes, for example 'language' or 'time-zone', then when it will be changed take some actions depending on the new value.
I thought of using setInterval, but I have many 'interval's in my website, so I don't want to overuse it, I'm worried that it may affect the user experience. Instead I found my self compelled to trigger the actions which I want to be done after the value changes in each method may change the variable's value, this is simple but makes my code a bit tightly coupled.
what do you suggest for that.
It seems like Object.observe would be pretty much exactly what you need; unfortunately it is currently proposed as a "post ECMAScript 6" spec, so it will be a while until it is widely available in browsers. There are shim implementations though (e.g. here or here), which could give you the same functionality in current browsers.
An alternative approach would be wrapping the object in question in a direct proxy, but those are part of ES6, and also not widely adopted by browsers yet.
In languages like C++, you'd do this with accessor methods.
For example, instead of accessing a property of a class with something like foo.bar, you'd say foo.getBar().
getBar() would look something like this:
this.getBar = function(){
console.log("bar was accessed");
return bar;
}
You should also have a method to set the value of bar, i.e.
this.setBar = function(newBar){
console.log("Setting the value of bar");
bar = newBar;
}
These methods will give you more control of your variables, too. For example, if someone tries to assign a string to something that should be an integer, you could throw an error. Or if you have a variable called "length", you could throw an error if someone tries to make it less than zero.
You should use Object.prototype.watch() to track variable's change
The watch() method watches for a property to be assigned a value and
runs a function when that occurs.
Watches for assignment to a property named prop in this object,
calling handler(prop, oldval, newval) whenever prop is set and storing
the return value in that property. A watchpoint can filter (or
nullify) the value assignment, by returning a modified newval (or by
returning oldval).
If you delete a property for which a watchpoint has been set, that
watchpoint does not disappear. If you later recreate the property, the
watchpoint is still in effect.
To remove a watchpoint, use the unwatch() method. By default, the
watch method is inherited by every object descended from Object.
there is not standard, but you can use the gist polifill created by eli-grey
Anyway this is a duplicate of Listening for variable changes in JavaScript or jQuery
Related
Eclipse has an option to warn on assignment to a method's parameter (inside the method), as in:
public void doFoo(int a){
if (a<0){
a=0; // this will generate a warning
}
// do stuff
}
Normally I try to activate (and heed) almost all available compiler warnings, but in this case I'm not really sure whether it's worth it.
I see legitimate cases for changing a parameter in a method (e.g.: Allowing a parameter to be "unset" (e.g. null) and automatically substituting a default value), but few situations where it would cause problems, except that it might be a bit confusing to reassign a parameter in the middle of the method.
Do you use such warnings? Why / why not?
Note:
Avoiding this warning is of course equivalent to making the method parameter final (only then it's a compiler error :-)). So this question Why should I use the keyword "final" on a method parameter in Java? might be related.
The confusing-part is the reason for the warning. If you reassign a parameter a new value in the method (probably conditional), then it is not clear, what a is. That's why it is seen as good style, to leave method-params unchanged.
For me, as long as you do it early and clearly, it's fine. As you say, doing it buried deep in four conditionals half-way into a 30-line function is less than ideal.
You also obviously have to be careful when doing this with object references, since calling methods on the object you were given may change its state and communicate information back to the caller, but of course if you've subbed in your own placeholder, that information is not communicated.
The flip side is that declaring a new variable and assigning the argument (or a default if argument needs defaulting) to it may well be clearer, and will almost certainly not be less efficient -- any decent compiler (whether the primary compiler or a JIT) will optimize it out when feasible.
Assigning a method parameter is not something most people expect to happen in most methods. Since we read the code with the assumption that parameter values are fixed, an assignment is usually considered poor practice, if only by convention and the principle of least astonishment.
There are always alternatives to assigning method parameters: usually a local temporary copy is just fine. But generally, if you find you need to control the logic of your function through parameter reassignment, it could benefit from refactoring into smaller methods.
Reassigning to the method parameter variable is usually a mistake if the parameter is a reference type.
Consider the following code:
MyObject myObject = new myObject();
myObject.Foo = "foo";
doFoo(myObject);
// what's the value of myObject.Foo here?
public void doFoo(MyObject myFoo){
myFoo = new MyObject("Bar");
}
Many people will expect that at after the call to doFoo, myObject.Foo will equal "Bar". Of course, it won't - because Java is not pass by reference, but pass by reference value - that is to say, a copy of the reference is passed to the method. Reassigning to that copy only has an effect in the local scope, and not at the callsite. This is one of the most commonly misunderstood concepts.
Different compiler warnings can be appropriate for different situations. Sure, some are applicable to most or all situations, but this does not seem to be one of them.
I would think of this particular warning as the compiler giving you the option to be warned about a method parameter being reassigned when you need it, rather than a rule that method parameters should not be reassigned. Your example constitutes a perfectly valid case for it.
I sometimes use it in situations like these:
void countdown(int n)
{
for (; n > 0; n--) {
// do something
}
}
to avoid introducing a variable i in the for loop. Typically I only use these kind of 'tricks' in very short functions.
Personally I very much dislike 'correcting' parameters inside a function this way. I prefer to catch these by asserts and make sure that the contract is right.
I usually don't need to assign new values to method parameters.
As to best-practices - the warning also avoids confusion when facing code like:
public void foo() {
int a = 1;
bar(a);
System.out.println(a);
}
public void bar(int a) {
a++;
}
You shoud write code with no side effect : every method shoud be a function that doesn't change . Otherwise it's a command and it can be dangerous.
See definitions for command and function on the DDD website :
Function :
An operation that computes and returns a result without observable side effects.
Command : An operation that effects some change to the system (for
example, setting a variable). An
operation that intentionally creates a
side effect.
So I learned a bit about the hidden class concept in v8. It is said that you should declare all properties in the constructor (if using prototype based "pseudo classes") and that you should not delete them or add new ones outside of the constructor. So far, so good.
1) But what about properties where you know the type (that you also shouldn't change) but not the (initial) value?
For example, is it sufficient to do something like this:
var Foo = function () {
this.myString;
this.myNumber;
}
... and assign concrete values later on, or would it be better to assign a "bogus" value upfront, like this:
var Foo = function () {
this.myString = "";
this.myNumber = 0;
}
2) Another thing is with objects. Sometimes I just know that an object wont have a fixed structure, but I want to use it as a hash map. Is there any (non verbose) way to tell the compiler I want to use it this way, so that it isn't optimized (and deopted later on)?
Update
Thanks for your input! So after reading your comments (and more on the internet) I consider these points as "best practices":
Do define all properties of a class in the constructor (also applies for defining simple objects)
You have to assign something to these properties, even if thats just null or undefined - just stating this.myString; is apparently not enough
Because you have to assign something anyways I think assigning a "bogus" value in case you can't assign the final value immediatly cannot hurt, so that the compiler does "know" ASAP what type you want to use. So, for example this.myString = "";
In case of objects, do assign the whole structure if you know it beforehand, and again assign dummy values to it's properties if you don't know them immediatly. Otherwise, for example when intending to use the Object as a hashmap, just do: this.myObject = {};. Think its not worth indicating to the compiler that this should be a hashmap. If you really want to do this, I found a trick that assigns a dummy property to this object and deletes it immediatly afterwards. But I won't do this.
As for smaller Arrays it's apparently recommended (reference: https://www.youtube.com/watch?v=UJPdhx5zTaw&feature=youtu.be&t=25m40s) to preallocate them especially if you know the final size, so for example: this.myArray = new Array(4);
Don't delete properties later on! Just null them if needed
Don't change types after assigning! This will add another hidden class and hurt performance. I think thats best practice anyways. The only case where I have different types is for certain function arguments anyways. In that case I usually convert them to the same target type.
Same applies if you keep adding additional properties later on.
That being said, I also think doing this will lean to cleaner and more organized code, and also helps with documenting.
Yeah, so one little thing I am unsure remains: What if I define properties in a function (for example a kind of configure() method) called within the constructor?
Re 1): Just reading properties, like in your first snippet, does not do anything to the object. You need to assign them to create the properties.
But for object properties it doesn't actually matter much what values you initialise them with, as long as you do initialise them. Even undefined should be fine.
The concrete values are much more relevant for arrays, where you want to make sure to create them with the right elements (and without any holes!) because the VM tries to keep them homogeneous. In particular, never use the Array constructor, because that creates just holes.
Re 2): There are ways to trick the VM into using a dictionary representation, but they depend on VM and version and aren't really reliable. In general, it is best to avoid using objects as maps altogether. Since ES6, there is a proper Map class.
I want to trigger an event whenever a variable is incremented. Is that possible?
var a = 0;
// if this variable gets incremented ++ to 1, I want to trigger an event.
// how can I create listener for it?
Google didn't help.
Directly like your example, it's not possible.
But, if the value is in an object, you could use a setter using defineProperty to know when a value is changed: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Eventually, you may be able to listen to changes on objects using Object.observe http://updates.html5rocks.com/2012/11/Respond-to-change-with-Object-observe
Support for legacy browsers
Note thought that defineProperty won't work on old browsers.
If you need to support old ones, you can create an interface to change object value and do what you want on the methods (like myInt.increment()). (This pattern is used inside Backbone, Ember and others)
Or you can do some dirty checking by running a loop (setTimeout) and comparing the new value with a cached old value... (This is the solution took by Angular.js)
Is there ANY way of monitoring primitive String declaration in NodeJS?
For example, when I do "test"; is there any way of triggering a special event with "test" as a parameter?
I am not sure what you mean by do "test;"; but if you want to trigger an event whenever a variable is assigned a new value, no, there is no way to trigger an event for variable changes.
If you want to watch a variable, it is better to re-design your system to make a call instead of assigning a variable. Instead of doing:
running_mode = "test";
require
switch_mode("test");
and call whatever event handlers you want to trigger on this update.
If you really want to watch the value of a global variable, you can do it by checking the value once in every turn of the main loop:
function is_mode_changed() {
if (running_mode=="test") event_handler();
process.nextTick(is_mode_changed);
}
Once you call this function, it will continue running once each turn of the main loop. If it what you want to do is something like following a variable to do some specific tasks time to time, like following a global counter and doing some cleanup tasks everytime counter reaches 1000, this is a good way to do. If what you want to do something immediately after a variable is changed, it is not possible.
I hope I could understand your question correctly.
UPDATE
[I am adding this in regards to the comment below which rendered everything above unrelated to question because I had misunderstood it.]
As you mentioned yourself, a string literal like "test" is a primitive value which is not an object. So, it is handled by the interpreter in a way we cannot alter.
From Ecma-262:
4.3.2 primitive value
member of one of the types Undefined, Null, Boolean, Number, or String as defined in Clause 8
NOTE: A primitive value is a datum that is represented directly at the lowest level of the language implementation.
To prevent confusion, Clause 8 is the section of standard on Types as listed above.
Since you specified V8, and not per-spec-ECMAScript, you have more concrete options at your disposal. In the V8 API there is classes/templates or primitives that are separate from those of object wrappers for primitives. In order to be able to hook in a way to know when this actually happens would likely require modifying v8 in a custom manner, but it is doable.
http://code.google.com/p/v8/source/browse/branches/bleeding_edge/include/v8.h#1017
Also much of the action takes place in js itself. Perhaps not the very constructor itself, but everything that happens thereafter. String.prototype.toString/valueOf.
http://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/string.js
I'm just curious how this is done directly by browsers. I heard that .length property of Array in Javascript Engines in fact uses invisible setters and getters to achieve functionality of ECMA-s standard that says: "whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted"). I understand that setter is needed in this case, but what with getter? Do we really need to call native getter to get this value? Or this is only a some mistake with understanding Javascript Engine somewhere?
A property is either implemented as a field or as setter/getter methods.
If it's a field then it's just a value, when setting the value nothing more happens than that the value changes.
If you have a setter method in order to perform something more whenever the value is set, you also have a getter method to match, even if the getter method doesn't do anything more than just return the value. You don't want to mix the two ways of implementing a property, it's just a lot simpler to go all the way in either direction.
Have a look at defineGetter and defineSetter. This might be how Firefox does it, but I'm not sure about the other browsers.
Does it really matter? .length could be implemented in c++ for all I know. It could be a builtin part of the javascript engine, and not really implementable in javascript in anyway. All that you, the user, needs to know is that the length holds the length of the array, and if you change it the length of the array changes.
For starters, the JavaScript Array object has a function property .length() which will return the current length of the array instance. Getters and setters can be defined in as of JavaScript 1.6 (I think) but it's not widely adopted and I haven't seen much use of it. The only difference between a getter and a function that returns a value is the syntax. Getters and setters can are called by the engine depending on direction of assignment.
var obj = {myProp:0}.myProp; // getting
obj.myProp = 1; // setting
The above example is a bit funky, but I think you get the idea...