Is such declaration of getter and setter for a property correct and most efficient?
var AxisRange = (function(){
function AxisRange(){
this._userMaxValue = 0.0;
Object.defineProperty(AxisRange.prototype, "UserMaxValue", {
get : function(){
return this._userMaxValue;
},
set : function(value){
if(value != this._userMaxValue){
this._userMaxValue = value;
this.validateUserMaxValue();
this.validateUserStep();
this.synchronizeActualRange();
}
}
});
}
AxisRange.prototype.validateUserMaxValue = function(){
alert("validateUserMaxValue");
};
return AxisRange;
})();
Also, I'm using JetBrains WebStorm to write my JS code, and it warns me that
AxisRange.prototype used in Object.defineProperty is not assignable to parameter type Object.
in line if(value != this._userMaxValue) is says "Possible invalid usage of this."
Before I go any further with code typing I need to make sure what I'm using is correct.
You're defining a prototype property inside the constructor. That means it will be re-defined every time you make a new AxisRange object. Move that out of the constructor function.
You also might want to get rid of that closure, because you're not using it to namespace any local variables and it will complicate attempts to optimize your JavaScript. (Google Closure Compiler will especially complain if you ever use it.)
Related
Performing a [[Get]] or [[Put]] operation on a throws a RangeError that states Maximum call stack size exceeded pointing to the this.a in the getter and the = in the setter.
let someObject = {
get a() {
return this.a;
},
set a(val) {
this.a = val;
}
}
someObject.a; // Error
someObject.a = 5; // Error
If the properties inside the getter and setter are underscored they work however:
let someObject = {
get a() {
return this._a_;
},
set a(val) {
this._a_ = val;
}
}
I've tested this in both the node environment and the v10 engine in Chrome and the same thing happens.
Such confusion. Send help.
Because by doing return this.a you're accesing the a property, which triggers the getter function, which accesses the a property, which triggers the getter function, which accesses the a property, which triggers the getter function... Endless loop.
Same for setter.
You need to have a variable that has a different name then the getter/setter. The most common way is to prefix the variable with an _.
Otherwise if you don't do this you will have an endless loop of calls to the getter/setter.
class A {
constructor() {
this._a = '';
}
get a() {
// If we don't call it like this
// We will be calling the getter again
// Which in return will call itself again
return this._a
}
}
Once an object has been defined with a setter for some property, that setter is always used to set the property value — even inside the setter itself! If you attempt to set the property with simple assignment inside the setter, JavaScript will call the setter again, and you get infinite recursion.
Using a leading special character like "_" for a second "secret name" is a common convention. However, that property is still externally visible (though it can be made non-enumerable). Another approach available in newer JavaScript environments is to use a Symbol instance instead of a property name. Symbol instances guarantee that your internal property identifier cannot ever collide with another property name from some other source in the application.
So:
let someObject = function() {
var aKey = Symbol();
return {
get a() {
return this[aKey];
},
set a(value) {
this[aKey] = value;
}
};
}();
That code uses a closure to create a private variable for the actual property key for what externally looks like a property called "a". It won't be possible for any other code to accidentally "step on" the private actual property used by the setter/getter pair because that's what Symbol is for.
I would like to override a Javascript built-in function with a new version that calls the original (similarly to overriding a method on a class with a version that calls super in many languages). How can I do this?
For example...
window.alert = function(str) {
//do something additional
if(console) console.log(str);
//super.alert(str) // How do I do this bit?
}
Store a reference to the original function in a variable:
(function() {
var _alert = window.alert; // <-- Reference
window.alert = function(str) {
// do something additional
if(console) console.log(str);
//return _alert.apply(this, arguments); // <-- The universal method
_alert(str); // Suits for this case
};
})();
The universal way is <original_func_reference>.apply(this, arguments) - To preserve context and pass all arguments. Usually, the return value of the original method should also be returned.
However, it's known that alert is a void function, takes only one argument, and does not use the this object. So, _alert(str) is sufficient in this case.
Note: IE <= 8 throws an error if you try to overwrite alert, so make sure that you're using window.alert = ... instead of alert = ....
There is no "super". Anyway, create a closure to "keep" around the original function-object.
Note the "self invoking function" that returns a new function-object (that is assigned to the window.alert property). The new function-object returned creates a closure around the variable original which evaluates to the original value of window.alert that was passed in to the "self invoking function".
window.alert = (function (original) {
return function (str) {
//do something additional
if(console) {
console.log(str)
}
original(str)
}
})(window.alert)
However, I believe some browsers may prevent alert and other built-ins from being modified...
Happy coding.
I'm assuming your question is how do you overwrite a built-in and still be able to call it. First off as a disclaimer, you should never overwrite built ins unless you have a good reason for doing it since it will make it impossible to debug/test.
This is how you would do it:
window._alert = window.alert;
window.alert = function(str) {
if(console) console.log(str);
window._alert(str);
}
How to do simple classical inheritance in Javascript:
SuperClass.call(this) // inherit from SuperClass (multiple inheritance yes)
How to override functions:
this.myFunction = this.myFunction.override(
function(){
this.superFunction(); // call the overridden function
}
);
The override function is created like this:
Function.prototype.override = function(func)
{
var superFunction = this;
return function()
{
this.superFunction = superFunction;
return func.apply(this,arguments);
};
};
Works with multiple arguments.
Fails when trying to override undefined or nonfunctions.
Makes "superFunction" a "reserved" word :-)
JavaScript does not use a classical inheritance model. There is a nice article here which describes a way to write your classes so that a similar syntax can be used, but it's not natively supported.
By using proxy object you can do this.
window.alert = new Proxy(window.alert , {
apply: function(target,that,args){
console && console.log(args.join('\n'));
target.apply(that,args)
}})
Stylistically, I prefer this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
};
To this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
};// var Filter = function(){...}
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
Functionally, are there any drawbacks to structuring my code this way? Will adding a prototypical method to a prototype object inside the constructor function's body (i.e. before the constructor function's expression statement closes) cause unexpected scoping issues?
I've used the first structure before with success, but I want to make sure I'm not setting myself for a debugging headache, or causing a fellow developer grief and aggravation due to bad coding practices.
Functionally, are there any drawbacks to structuring my code this way?
Will adding a prototypical method to a prototype object inside the
constructor function's body (i.e. before the constructor function's
expression statement closes) cause unexpected scoping issues?
Yes, there are drawbacks and unexpected scoping issues.
Assigning the prototype over and over to a locally defined function, both repeats that assignment and creates a new function object each time. The earlier assignments will be garbage collected since they are no longer referenced, but it's unnecessary work in both runtime execution of the constructor and in terms of garbage collection compared to the second code block.
There are unexpected scoping issues in some circumstances. See the Counter example at the end of my answer for an explicit example. If you refer to a local variable of the constructor from the prototype method, then your first example creates a potentially nasty bug in your code.
There are some other (more minor) differences. Your first scheme prohibits the use of the prototype outside the constructor as in:
Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)
And, of course, if someone used:
Object.create(Filter.prototype)
without running the Filter constructor, that would also create a different result which is probably not as likely since it's reasonable to expect that something that uses the Filter prototype should run the Filter constructor in order to achieve expected results.
From a run-time performance point of view (performance of calling methods on the object), you would be better off with this:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
this.checkProduct = function( product ){
// run some checks
return is_match;
}
};
There are some Javascript "experts" who claim that the memory savings of using the prototype is no longer needed (I watched a video lecture about that a few days ago) so it's time to start using the better performance of methods directly on the object rather than the prototype. I don't know if I'm ready to advocate that myself yet, but it was an interesting point to think about.
The biggest disadvantage of your first method I can think of is that it's really, really easy to make a nasty programming mistake. If you happen to think you can take advantage of the fact that the prototype method can now see local variables of the constructor, you will quickly shoot yourself in the foot as soon as you have more than one instance of your object. Imagine this circumstance:
var Counter = function(initialValue){
var value = initialValue;
// product is a JSON object
Counter.prototype.get = function() {
return value++;
}
};
var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get()); // outputs 10, should output 0
Demonstration of the problem: http://jsfiddle.net/jfriend00/c7natr3d/
This is because, while it looks like the get method forms a closure and has access to the instance variables that are local variables of the constructor, it doesn't work that way in practice. Because all instances share the same prototype object, each new instance of the Counter object creates a new instance of the get function (which has access to the constructor local variables of the just created instance) and assigns it to the prototype, so now all instances have a get method that accesses the local variables of the constructor of the last instance created. It's a programming disaster as this is likely never what was intended and could easily be a head scratcher to figure out what went wrong and why.
While the other answers have focused on the things that are wrong with assigning to the prototype from inside the constructor, I'll focus on your first statement:
Stylistically, I prefer this structure
Probably you like the clean encapsulation that this notation offers - everything that belongs to the class is properly "scoped" to it by the {} block. (of course, the fallacy is that it is scoped to each run of the constructor function).
I suggest you take at the (revealing) module patterns that JavaScript offers. You get a much more explicit structure, standalone constructor declaration, class-scoped private variables, and everything properly encapsulated in a block:
var Filter = (function() {
function Filter(category, value) { // the constructor
this.category = category;
this.value = value;
}
// product is a JSON object
Filter.prototype.checkProduct = function(product) {
// run some checks
return is_match;
};
return Filter;
}());
The first example code kind of misses the purpose of the prototype. You will be recreating checkProduct method for each instance. While it will be defined only on the prototype, and will not consume memory for each instance, it will still take time.
If you wish to encapsulate the class you can check for the method's existence before stating the checkProduct method:
if(!Filter.prototype.checkProduct) {
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
}
There is one more thing you should consider. That anonymous function's closure now has access to all variables inside the constructor, so it might be tempting to access them, but that will lead you down a rabbit hole, as that function will only be privy to a single instance's closure. In your example it will be the last instance, and in my example it will be the first.
Biggest disadvantage of your code is closing possibility to override your methods.
If I write:
Filter.prototype.checkProduct = function( product ){
// run some checks
return different_result;
}
var a = new Filter(p1,p2);
a.checkProduct(product);
The result will be different than expected as original function will be called, not my.
In first example Filter prototype is not filled with functions until Filter is invoked at least once. What if somebody tries to inherit Filter prototypically? Using either nodejs'
function ExtendedFilter() {};
util.inherit(ExtendedFilter, Filter);
or Object.create:
function ExtendedFilter() {};
ExtendedFilter.prototype = Object.create(Filter.prototype);
always ends up with empty prototype in prototype chain if forgot or didn't know to invoke Filter first.
Just FYI, you cannot do this safely either:
function Constr(){
const privateVar = 'this var is private';
this.__proto__.getPrivateVar = function(){
return privateVar;
};
}
the reason is because Constr.prototype === this.__proto__, so you will have the same misbehavior.
In Javascript, I have an object that contains a member variable called "dialogHost". It is itself an object that can call different functions. Currently, the way I have it set up is that in most cases, the object's dialogHost value is undefined. In the rare cases where it needs to be defined, I define it to be something like "window.parent" for example. The problem with setting it up this way is that any time I need to use this member variable, I have to check whether it is defined first, like:
var myDelegate;
if (typeof (myObject.dialogHost) !== 'undefined') {
myDelegate = myObject.dialogHost.someFunction;
} else {
myDelegate = someFunction;
}
myDelegate(...);
I have to do this type of check in a few places and it would be nice if the value always existed. Should I simply provide a default value of "window" for dialogHost in this case? I'm not sure if that is a good idea or not. Basically, I want the default value to be such that I can simply call:
// This would be equivalent to myDelegate(...) above...
myObject.dialogHost.someFunction(...);
Without having to do the above checks every time. Is there a way to do this?
In JavaScript the very good practice is development with "avoiding global variables as much you can".
Should I simply provide a default value of "window" for dialogHost in
this case? - No, don't rely on global window object. Use closures and immediate functions.
var myObject = {
'dialogHost': function(){
// doing some good stuff
}
},
myDelegate;
myDelegate = (function(obj){
function someFunction(){ // local function, not accessible from outside
// doing some good stuff too
}
return (typeof obj.dialogHost === 'function')? obj.dialogHost : someFunction;
}
)(myObject);
// Now you can use myDelegate() function anywhere below
myDelegate(...);
Other than coding style is there any advantages/disadvantages to either:
Circle.prototype = { radius : 10};
Object.defineProperty(Circle.prototype, 'circumference', {
get: function() { return 2*Math.PI*this.radius; }
});
vs
Circle.prototype = {
radius : 10,
get circumference() { return 2*Math.PI*this.radius; }
}
In property definition, JavaScript handles it via the internal method DefineOwnProperty, where assignment is handled by the internal method Put. In short, the second one checks whether or not a property is read-only and if yes, leads to rejection.
This can have consequences when using read-only properties, which prevent assignment, but not definition.
If you want to create a new property it is better use definition. If you want to change the value of a property, you can use assignment.
Take a look here for more, very interesting article.
EDIT: In fact, defineProperty is used for reasons such as defining read only properties and other reasons about the behavior of the property defined.
Take a look here for more too.