How do you properly OOP with Javascript and clearly specify variable scopes? - javascript

In Introduction to Object-Oriented JavaScript, a formal description is given on how to use javascript in an object oriented fashion. Your code for functions inside objects would like along the lines of:
$(function() {
var oPerson = new cPerson("Florian");
alert("Hi! My name is " + oPerson.sMyNameIs());
});
function cPerson(sSetName)
{
var sName= sSetName;
var oPersonInst = this;
this.sMyNameIs = function () {
return sName;
};
}
With a bit more experience, you probably want a more clearcut reference to the instantiated class, so you modify the class code as such (and I add another function too):
function cPerson(sSetName)
{
var sName= sSetName;
var oPersonInst = this;
this.sMyNameIs = function () {
return oPersonInst.sName;
};
this.sMyFullNameIs = function () {
return oPersonInst.sMyNameIs();
};
}
Now we have come accross three different ways of referring to function or variables from within class functions:
return sName;
return this.sName;
return oPersonInst.sName;
Suppose I want to call the sName variable in the instantiated class very specifically, and these example functions will get more and more and even more complex and in depth as development goes on.
I think that the first option ('return sName;') is uncertain, as you are not quite sure whether you are referring to the variable in the right targeted instantiated class scope. It could be an accidental local var that you are calling.
The second, using this, IMHO, is also not perfect as this apparently changes depending on situations, and you can't (?) rely on that you are calling the right variable in the instantiated class specifically.
So the third reference, is IMHO, the best looking reference. Very specifically defined right at instantiation of the class. How can there be any doubt that the var sName of the class is meant.
Q1: Why are functions in the class defined with this.? Can it not better be defined with oPersonInst.something = function () { //... }; ?
Q2: why does, in code that I have given, alert(oPersonInst.sMyNameIs()); work, but alert(oPersonInst.sName); does not (at least, not within $.each( something, function() { //right here }) ), but alert(sName); DOES work (not favored IMHO, because of the above mentioned reasons)?
Q3: Can someone pot some exemplary code, or maybe even change this sample code, where solid out-of-local-scope references are used, that will work outside as well as inside $.each(...) callback functions (or other callback related functions) ?
Forgive my confusion, we're all learners, and I feel a hole in my brain. This article did not explain my concerns over this very well.

this doesn't change randomly at all.. it always means the current closure (function):
if you are in function_1() -- this means function_1
if you are in function_1>function_2 -- function_2 is the current closure and this means function_2
IF you need function_1's this in function_2 you have to capture it while in function_1: meaning var function1This = this;
and the way to reference a var by using the functions name before it means static access. It has different semantics
so use this.var to be sure you get the INSTANCE's variable
use a 'captured this pointer' to access your parents INSTANCE's variable
and only use name.var if you want to get the static, shared (between all instances) value

Related

Cannot combine dynamic prototype pattern with prototype chaining [duplicate]

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.

How can I use closures with function pointers?

My goal is to use closures while still writing clean code. One thing I noticed is that somehow I always end up repeating myself because one of my anonymous functions is needed in more than one case.
To this goal, I want to have these repeated functions stored in an object which I can later reuse.
Now, to my question. I've created this example http://jsfiddle.net/tiagoespinha/tTx64/ and the alert will not fire, because y is null.
However, if I inline the function, everything works fine http://jsfiddle.net/tiagoespinha/tTx64/1/
Is there a trick to work around this? How can I have it working in the first example? The variable y is still there, why can't JS catch it?
You want objects having own variables (y) and sharing functions.
What you really need is probably prototype.
function Holder() {
this.y = 5;
this.myFn();
}
Holder.prototype.myFn = function() {
alert("The value of the closure var is " + this.y);
}
new Holder();
I'd suggest the reading of Introduction to Object-Oriented JavaScript so that you don't try to rebuild OOP with just closures.
//our constructor, each instance will carry a y of 5
function Proto() {
this.y = 5;
}
//a shared function for all instances
Proto.prototype.returnedFn = function() {
alert("The value of the closure var is " + this.y);
}
//just a wrapper for the new instance call.
//I just like it this way to avoid using "new" when making instances
function newFn() {
//return a new instance
return new Proto();
}
//test it out
newFn().returnedFn();
newFn().returnedFn();
Your first example would need some kind of dynamic scoping to work. Javascript is statically scoped.
Closures allow a function to capture some local variables from the scope it's defined in. Holder.myFn isn't defined in a scope that contains variable y.
Also note that every instance of a function has its own closure. Hence it's not possible to define your function once and have it refer to different y's in different contexts. (In your second example the inner function is defined every time you call newFn, so many instances can exist, each with its own copy of y.)
I will also add an answer to my own question to report my findings.
Based on the other solutions provided and partly using the OOP solution, I found another way which also makes use of closures.
// Object prototype which takes an argument
function MyObj(abc) {
// Declare function using a closure
// and thus being able to use the argument
this.myFn = (function(){
return function() {
alert("abc is " + abc);
};
})();
}
// Then we can simply create an object with the
// desired argument and the function will behave as expected
var v = new MyObj(10);
v.myFn();
I think nobody provided this solution possibly because I omitted that I don't really want to store the values locally in the object. I simply want to pass some values in, make use of them in one function and then get rid of the object.
In this case I believe a pure OOP solution might be overkill.
Anyhow, thank you for all the proposed solutions!​

Question about Javascript model construction

I'm working on implementing a Javascript model on a web app that I'm working on. The purpose of the model is to simply hold information about the state of the page. I have come across two different implementations for creating the model and I was wondering which one was the best to use. The first implementation:
var PageInfo = function () {
this._info = {};
};
PageInfo.prototype = {
getInfo: function () {
return this._info;
},
setInfo: function (updatedInfo) {
this._info = updatedInfo;
}
};
The 2nd implementation:
var pageInfo = function () {
var info = {};
return {
getInfo: function () {
return info;
},
setInfo: function (updatedInfo) {
info = updatedInfo;
}
}
};
Another question I have is about the setInfo() function. When I find myself updating the model, I often want to have the info that I just changed immediately available to me. This has led me to write the setter function as such:
setInfo: function(updatedInfo) {
info = updatedInfo;
return info;
}
which I implement in the code like so:
var info = pageInfo.setInfo(newInfo);
Is this ok or should I be implementing it like this?:
pageInfo.setInfo(newInfo);
var info = pageInfo.getInfo();
Just trying to follow best practices and avoid any issues that may come up from using the wrong implementation.
Both implementations are perfectly acceptable. The former will be faster, albeit by a negligible amount, but exposes its internals to the world. This means that any variable that holds a reference to an instance of PageInfo will be able to manipulate the _info property. Generally this is a non-issue as properties that being with an underscore (_) are considered to be private and should be left alone.
The latter implementation makes use of a concept called closure. A closure is formed when a value is returned that maintains a reference to its defining scope. Essentially it means that the info variable is kept alive. Since the variable is "closed over" it's impossible for it to be modified outside of the interface methods that you provide. In my experience this is rarely needed.
In regards to your second question, again either is acceptable. I like the interface for accessor methods to be consistent so I would say that setInfo should not return anything but there are exceptions to every rule. The exception to the rule occurs when the the value returned by getInfo will not be congruent with what was passed to setInfo. That is, if getInfo returns different value than the value passed to setInfo you might want to return the value out of setValue. Otherwise, the caller could simply re-use the value that was passed to setValue instead of calling getValue.
1st implementation is better, as in 2nd implementation every time you call pageInfo function, you are defining 2 new functions (or set up a closure), while 1st implementation is defining them in prototype and reusing.
For other question, if you only do this to preserve lines, i might suggest something like:
var info = pageInfo.setInfo(newInfo) || pageInfo.getInfo();
assuming setInfo returns undefined.

Javascript - get a variable from inside the local scope of a function

I am not great with anything beyond basic javascript so please forgive the simple question.
I am using the jsDraw2D library. This library has a graphics object that looks something like the following:
function jsGraphics(canvasDivElement) {
var canvasDiv;
this.drawLine = drawLine;
function drawLine(point1, point2) {
// do things with canvasDiv
}
}
You use it like this:
var gr = new jsGraphics(document.getElementById('canvas'))
gr.drawLine(new jsPoint(0,0), new jsPoint(10,10))
I would like to add a function to jsGraphics so that I can call
gr.getCanvasElement()
Is there a way to do this without editing the library itself?
I have tried
jsGraphics.prototype.getCanvasElement = function() { return canvasDiv }
but this doesn't seem to work. I have an intuitive feeling that its something with that new keyword but if you could explain why exactly it doesn't that would be helpful too.
Nope, this isn't using the normal JavaScript prototype-based inheritance, it's adding a separate drawLine function to every instance of jsGraphics, each with a closure around its own canvasDiv variable.
Once function jsGraphics() { is closed } there is no further way to access the canvasDiv variable at all, unless one of the functions inside provides access to it. This is often done deliberately to make private variables, explicitly to stop you getting at canvasDiv.
You can't just get to the canvasDiv element necessarily, because if it is never assigned to the object in the constructor using the this keyword, the reference to that object exists in a closure created by the constructor function itself.
You can however wrap the constructor in a new constructor and then set the prototypes equal:
function myJsGraphics(canvasDivElement) {
this.canvasDiv = canvasDivElement;
jsGraphics.call(this, cavasDivElement);
}
myJsGraphics.prototype = jsGraphics.prototype;
Now you should be able to access the element using your new constructor:
var obj = new myJsGraphics(document.getElementById('blah-elem'));
elem = obj.canvasDiv;
The whole closure thing is a little weird if you're not used to it, but the gist is that functions defined in a certain scope but available elsewhere can refer to variables in the scope in which they were defined at all times. The easiest example is when you have a function that returns a function:
function makeIncrementer(start) {
return function () { return start++; };
}
var inc = makeIncrementer(0);
var inc2 = makeIncrementer(0);
inc(); // => 0
inc(); // => 1
inc(); // => 2
inc2(); // => 0
That reference to the "start" variable is "closed over" when the function is returned from the makeIncrementer function. It cannot be accessed directly. The same thing happens in an object's constructor, where local variables are "closed" into the member functions of the object, and they act as private variables. Unless there was a method or variable reference to a private member defined in the constructor, you just can't get access to it.
This "private state" technique has become more and more idiomatic in the last few years. Personally I've found it oddly limiting when trying to quickly debug something from the console or override behavior in a 3rd party library. It's one of the few times I think "Damn it, why can't I do this with the language". I've exploited this bug in Firefox 2 to good effect when I've really needed to debug a "private variable" quickly.
I'd be curious to know when others use this idiom or when they avoid it. (#bobince I'm looking at you).
Anyway #bobince has pretty much answered your question (nutshell: No, you can't access the canvasDiv variable from the scope you are in).
However, there is one thing you can do that is a tradeoff between a hack or editing the 3rd-party library (I always go for the hack ;): you can augment the object to hold a reference you know you will need later.
Hack 1: if you control the object instantiations yourself:
var canvas = document.getElementById('canvas');
var gr = new jsGraphics(canvas);
gr._canvasDiv = canvas; // Augment because we'll need this later
// Sometime later...
gr._canvasDiv; // do something with the element
If the library supports some concept akin to a destructor (fired on unload of the page or something), be sure to null out or delete your property there too, to avoid memory leaks in IE:
delete gr._canvasDiv;
OR Hack 2: Overwrite the constructor just after including the library:
// run after including the library, and before
// any code that instantiates jsGraphics objects
jsGraphics = (function(fn) {
return function(canvas) {
this._canvasDiv = canvas;
return fn.apply(this, arguments)
}
}(jsGraphics))
Then access the element (now public) as gr._canvasDiv. Same note about deleting it on page unload applies.

Declaring functions in JavaScript [duplicate]

This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed last year.
What's the difference between these two ways of declaring a function?
function someFunc() { ... }
var someFunc = function() { ... }
I'm not asking in the technical sense. I'm not asking which is better for readability, or which style is preferred.
I am on different opinion with most of the people here. Technically this syntax may mean the same for declaring functions both ways
(I stand incorrect on my last statement. I read up on a diff post why they are technically diff and I'll add in the end, why)
; but the way they play a role in evolving patterns is massive. I would highly recommend "Javascript: The Good Parts" by Doughlas Crockford.
But to prove my point in a subtle and a simple manner; here is a small example.
//Global function existing to serve everyone
function swearOutLoud(swearWord) {
alert("You "+ swearWord);
}
//global functions' territory ends here
//here is mr. spongebob. He is very passionate about his objects; but he's a bit rude.
var spongeBob = {
name : "squarePants",
swear : function(swearWord) {
name = "spongy";
alert("You "+ swearWord);
return this;
}
}
//finally spongebob learns good manners too. EVOLUTION!
spongeBob.apologize = function() {
alert("Hey " + this.name + ", I'm sorry man!");
return this;
}
//Ask spongebob to swear and then apologize in one go (CASCADING EFFECT!!)
alert(spongeBob.swear("twit").apologize());
if you look at the code above I declared a function with a name swearOutLoud. Which would take a swear word from any object or a call and will give you the output. It can do operations on any object using the "this" parameter that is passed to it and the arguments.
However second declaration is declared as an attribute of object called "spongeBob". This is important to note; as here I am moving towards an object driven behavior. While I am also maintaining "cascading effect" as I return "this" if i have nothing else to return.
Somthing similar is done in jquery; and this cascading pattern is important if you are trying to write a framework or something. You'll link it to Builder design pattern also.
But with functions declared as an attributes of an object I am able to achieve an object centric behavior which leads to a better programming paradigm. Unless designed well; individual functions declared outside with global access lead to a non-object oriented way of coding. I somehow prefer the latter.
To see cascading in effect, look at the last statement where you can ask spongebob to swear and apologize at once; even though apologize was added as an attribute later on.
I hope I make my point clear. The difference from a technical perspective may be small; but from design and code evolution perspective it's huge and makes a world of a difference.
But thats just me! Take it or leave it. :)
EDIT:
So both the calls are technically different; because a named declaration is tied to global namespace and is defined at parse time. So can be called even before the function is declared.
//success
swearOutLoud("Damn");
function swearOutLoud(swearWord) {
alert("You " + swearWord)
}
Above code will work properly. But code below will not.
swear("Damn!");
var swear = function(swearWord) {
console.log(swearWord);
}
One advantage of using function someFunc() { ... } is that the function name appears in Firebug debugger. Functions that are declared the other way (var someFunc = function() { ... }) come up as anonymous.
Actually, the difference is that the second declaration gives us the ability to declare functions like this making it possible to have a function as a property for an object :
var myObject=new Object();
myObject.someFunc=function() { ... };
Style wise the second example is more consistent with other common ways to declare functions and therefore it could be argued that it is more readable
this.someFunc = function() { ... }
...
someFunc: function() { ... },
However, as also mentioned it's anonymous and therefore the name does not appear when profiling.
Another way to declare the function is as follows which gets you the best of both worlds
var someFunc = function someFunc() { ... }
Another difference is that, on most browsers, the latter allows you to define different implementations depending on circumstances, while the former won't. Say you wanted cross-browser event subscription. If you tried to define a addEventListenerTo function thusly:
if (document.addEventListener) {
function addEventListenerTo(target, event, listener) {
....
}
} else if (document.attachEvent) {
function addEventListenerTo(target, event, listener) {
....
}
} else {
function addEventListenerTo(target, event, listener) {
....
}
}
on some browsers, all the functions end up being parsed, with the last one taking precedence. Result: the above just doesn't work. Assigning anonymous functions to variables, however, will work. You can also apply functional and basic aspect oriented programming techniques using anonymous functions assigned to variables.
var fib = memoize(function (n) {
if (n < 0) return 0;
if (n < 2) return 1;
return fib(n-1) + fib(n-2);
});
...
// patch the $ library function
if (...) {
$ = around($, fixArg, fixResult);
}
It is both true that the first form:
function test() { }
is a more recognized syntax and that the second form:
var test = function() { ... }
allows you to control the scope of the function (through the use of var; without it, it would be global anyway).
And you can even do both:
var test = function test() { ... test(); ... }
This allows you to define a recursive function in the second form.
For readability, I'd say the first is clearly better. A future maintenance programmer, even assuming they're familiar enough with javascript to know many of the finer points coming up in this thread, are going to assume the first format.
For example, if they should some day want to ctrl-f to search for the definition of your function to see what's happening in there, are they going to first search for someFunc = function() or function someFunc()?
Also, to get downright typographical about it (since we're talking readablity) readers are often scanning the text quickly, and would be more inclined to skip over a line that starts with "var" if they're looking for a function definition.
I know this is a non-technical answer, but it's harder for humans to read code than computers.
When you write
function Test() {
}
JavaScript is really creating a property to which it assigns the function object that once called will execute the code reported in the function definition. The property is attached to the object window, or to the object that contains the function definition.

Categories

Resources