I was searching up how to fade an element with JavaScript earlier and I came across this function (object). I began wondering how does it work?
var fadeEffect=function(){
return{
init:function(id, flag, target){
this.elem = document.getElementById(id);
clearInterval(this.elem.si);
this.target = target ? target : flag ? 100 : 0;
this.flag = flag || -1;
this.alpha = this.elem.style.opacity ? parseFloat(this.elem.style.opacity) * 100 : 0;
this.si = setInterval(function(){fadeEffect.tween()}, 20);
},
tween:function(){
if(this.alpha == this.target){
clearInterval(this.elem.si);
}else{
var value = Math.round(this.alpha + ((this.target - this.alpha) * .05)) + (1 * this.flag);
this.elem.style.opacity = value / 100;
this.elem.style.filter = 'alpha(opacity=' + value + ')';
this.alpha = value
}
}
}
}();
I know that this is self invoking and only returns one object with two methods. My main concern this why does it use the this keyword? I am assuming the ‘this’ keyword is a placeholder for the object name “fadeEffect”. I would understand if ‘this’ was used to create multiple objects… but why is it used here?
One other thing bothering me is this ternary operator…
this.target = target ? target : flag ? 100 : 0;
How the heck does that work? It’s like two ternary operators combined into one which I never thought was possible?
Think of it as a namespace. the
thiskeyword refers back to the object literal that the self invoking function returns. This means thatthis.targetis accessible in the global namespace (or whatever scope thefadeEffectwas defined) as an object property:fadeEffect.target, but it doesn’t interfere with other variables that may exist in the outer scope.The two methods set new properties of the returned object, that’s all there is to it. Personally I find this to be, well, bad code… a closure would have been the better choice in this example:
This does the same thing, but other code cannot interfere with the values of the target, or mess up the interval etc… you’re right to say that the
thiskeyword isn’t required in this case, but I think the person who wrote this was either unfamiliar with JS closures, or at least insecure about how they work. This code effectively simulates a singleton pattern, or at least treats the object literal as an instance of a class. My guess is, the author is familiar with classical OOP, but not with prototypal inheritance. Anyway, the above code is safer, and safer is better IMHOOn the matter of your nested ternary, I’ve checked the code below using JSLint, and it suggested an even shorter, yet clearer alternative: use the default operator, followed by a ternary:
Anyway, here’s the same code, only not using the dangerous
thisconstructs, but using a closure, one of JavaScripts amazingly powerful features BTW, worth taking a closer look at what you can do with them!This way, the
tweenmethod cannot be called but by the interval, and the element on which the object, and its methods/functions are working their magic can never be overridden by external operations, they are inherent to the object. This makes for a safer construction, what’s more, you can only really mess up 1 method: override the.initmethod, and the object is rendered useless, but harmless. Compare that to your code, where you could mess up both methods, but leave the interval standing… that’s bad news: the interval would end up looking for a callback function that could very well have been deleted, causing your code to fail miserably: