Is it bad javascript practice to not assign a newly created object to a variable if you're never going to access it?
For example:
for(var i=0;i<links.length;i++){
new objectName(links[i]);
}
And again, I won't be accessing it, so there's no need for a variable to reference it.
If you're not accessing it but it's still useful, that suggests that the constructor itself has visible side effects. Generally speaking, that's a bad idea.
What would change if you didn't call the constructor at all?
If your constructor is doing something to the global state, that strikes me as very bad. On the other hand, you could be using it just for the sake of validation - i.e. if the constructor returns without throwing an exception, it's okay. That's not quite so bad, but a separate method for validation would make things a lot clearer if that's the case.
That’s absolutely fine if you don’t need to use it again.
"Is it bad javascript practice to not
assign a newly created object to a
variable if you're never going to
access it?"
I feel it is bad practice to make an assignment that is not needed, and, I would argue, not just for javascript but in general. If there are side-effects you want, getting them from the action of an assignment is bad practice for the simple reason that it would be fairly opaque from a maintenance point of view.
.
It seems like your constructor is doing something else besides creating/initializing an object.
It would be a cleaner solution to implement that extra functionality into a function or method.
Constructors should be used to create and initialize objects.
That’s absolutely fine if you don’t need to use it again. But we need to explain why.
An object can continue to do something, even if you don't have a reference to it (like other suggested, an animation, a listener, etc.)
Who think this is odd, should reflect on the alternatives before say this is not fine:
Maybe someone forget to assign the object to a variable? Maybe he made an even worse mistake: he forget to use it later. Is it reasonable? Is it Odd?
Is new objectName().start() more clear? maybe. But if you always need to call start() immediately after creation to make the object useful, it is better to include the start() in the costructor. This way you can't forget to do it.
If you can do it with a static method, without constructors inside, then the real question is: Why do you have an Object? a simple function should be enough.
If you create a static method only to create new Object, from one side maybe is more clear that it will do something (but you should anyway assume that a constructor can do something, this is a fact) on the other side is less clear that something can continue acting after the call. If you are not in the previous case (no creation of objects), maybe it is better to emphatize on the creation of something using a constructor. But what is more clear is subjective and can be pointless to argue more.
A good Object name can clarify or suggest that the object will do something, after creation.
Examples:
new Baby() is supposed to start to cry, sometimes. And he will live even if you don't tell him to to something.
new AutoRegisteringListener(); Really need to explain what will happen when you create such object? are you really surprised that this listener will register itself to some events?
In my opinion, the point is to think in object-oriented way, instead of thinking only in functional way: objects can have behaviour. This is what they are designed for, among other things.
Related
I'm wondering if i can get something like this:
function foo() {
console.log(xxx);
}
var myFunc = new foo();
I want console.log to give me 'myFunc' string (or object, or anything I can reference to for that matter)
Is that at all possible in JavaScript?
Sorry for my poor language - not a native speaker and a self-taught developer :)
EDIT
Maybe I should explain the reason for why I "need" this. Let's say I have a plugin that creates an interactive object in DOM. I can receive events from other object (WebSocket) that can be viable to any created object, but I can't be sure which one. Of course, I can handle this by creating some helper objects and/or functions, but it would really help to make my code a bit clearer if I could reference that object based on some DOM element that exists on the page.
It would be great if I could add a data attribute to an element that contains said created interactive object, and then - by finding a class name that exists within it - reference a variable that was constructed based on that constructor function.
Yes, I realize that this is not the best way to handle this situation, but:
This would reduce code complexity in my case
I'm just wandering if it's possible :)
A decorator adds additional functionality to an object by "wrapping" around the original value.
Is there a name for an object or function that ingests a pre-constructed object and adds additional functionality to it via mutation?.
Example:
function mutatesObjects(target) {
target.additionalFunctionality = "I've been mutated!";
}
This is similar to a contrcutor or factory except that it is adding functionality to an object that was already created.
Is there a name for this pattern?
Depending on the purpose for this change, Monkey Patching might apply.
"A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program)."
I would suggest Plugin name as a reference to jquery plugins.
But I also think this is actually an anti-pattern in most cases. This not only breaks the encapsulation (one of the main concepts in OOP), it goes even beyond it and changes object functionality.
Imagine a simple case where you do something like:
doSomething(object)
In the best case you can hope the object state was not changed. In the worse case you can suspect that it was mutated and it's state changed.
It's really unexpected if you get something completely different with new methods or properties.
But of course, there can be good usages (like jquery plugins).
I know that if you have some javascript function and you want to call it such that using this within it would refer not to the object on which it was directly called you can use func.call(thatObject,param,and,more,params...).
But suppose you are the writer of func and the only usage for func is via func.call,
Why would you not define it to begin with as:
function func(that,param,and,more,params...) {
//and in here use *that* and not *this*
}
yep, it looks less "cool" because its not a method of an object,
but hey if the only usage for func is via func.call it all seems like just extra code and overhead.
Am I missing something here? or is the source code in which I have seen this pattern just "over OOed" ?
There appears to be a large performance difference. Using
func(){
//code here, this.something
}
func.call(thatObject)
according to the first couple of tests is about 8 times slower than using
func(that){
//code here, that.something
}
func(thatObject)
Test it yourself, JSPerf here
Ultimately though, speed alone is rarely the most important factor in which code we use. Code is designed for people as much as it is for computers, we need to communicate our intentions clearly to both. Whichever makes the code cleanest is best, and we should follow conventions whenever it is feasible. I personally prefer the second option here, but I think the general convention is the first. So I think you use call in most situations, except for when you need the fastest code possible or if the convention changes.
Your pattern will work in this scenario but in general it has some problems ...
Constructor functions -> We create objects by using new keyword where 'this' object is automatically created and returned (default) also has the link with the function's prototype.
When calling the function someone might forget to pass 'that' object and your code will fail. In case of call if you pass null it is reset to global object (non-strict mode which is common)
func.call is intended to be used when an alternative (or any) context for the function is needed to be provided.
Your suggestion is odd, since, when you define the function using this pattern:**
function func(that,param,and,more,params...) {
//and in here use *that* and not *this*
}
it's either:
doesn't belong to any object
in which case passing an object to act as this doesn't make any sense, since there should be no this.someThing calls to begin with
or belongs to a different object or is defined to be a plug to an object
in which case it does exactly what func.call would do, while contaminating the definition of the function with redundant parameter.
UPDATE:
Think of the second example in this way - imagine that some set of Objects (what you'd call from the same "class") allow injection of arbitraty functions, say for iteration over all properties of the object and some summary or manipulation or what have you.
In Java, the common pattern is to create an Iterator and pass it, and its main purpose is to serve as sort of placeholder so that next and hasNext methods can be called - since Java doesn't really have object-less functions. (granted there is some additional logic there, but let's leave it alone for the sake of this discussion).
JavaScript does not neeed this! All these call and apply methods do not need to have some additional Iterator object to hold them. They can be defined "detached" from any object, while still with intention to be used in a context of one (hence this usage in their code) and injected into code that knows to accept such functions.
The "host" code than only needs to call or apply them, knowing that this will refer to itself - this very "host" object.
This leads to a more concise, reusable and portable code, IMO.
UPDATE 2:
See more here.
I understand from this post, that it's an anti-pattern to modify Object's prototype in JavaScript. I was curious, however, if it's widely considered to be an antipattern to modify other 'built-in' prototypes.
For example: say we wanted to add a setPixel(x,y,color) function to CanvasRenderingContext2D - to abstract out the duty of getting the context's image data, setting a pixel to a certain color, and putting the image data back.
CanvasRenderingContext2D.prototype.setPixel = function(x, y, color){
var imgdata = this.createImageData(1,1);
imgdata.data[0] = color.r;
imgdata.data[1] = color.g;
imgdata.data[2] = color.b;
imgdata.data[3] = color.a;
this.putImageData(imgdata,x,y);
};
I haven't tested this code, but you get the idea. Is something like this against 'best practices' ?
I wouldn't do it as it makes it hard to track what is implemented where. It also introduces the risk of two people overriding the same behavior.
Generally, if you are adding a prototype to one of the base objects in JavaScript, you should have a good reason, and there is really no reason to modify Object, since you don't know how to predict what the end result will be of that modification.
I tend to add startsWith, trim and some other functions to String, for example, as these are helper functions, just as adding some functions to Array that exists for Firefox but not IE just makes sense (such as the filter function).
So, adding to the Canvas is fine, but, what if someone is using your library, and using excanvas. Will it cause a problem?
You either may want to explore that, or document that it doesn't work for excanvas, and if you have a small test to show that, please include it, so that if later there is a new version, and your problem disappears people can verify that.
UPDATE:
You will want to do this:
if (!CanvasRenderingContext2D.setPixel) {
...
}
That way, if someone did include one by that name you will not overwrite it, but you will need to handle it gracefully.
Definitely not; if the method is related to the object in this way then it is an elegant solution.
All of these "anti-pattern" suggestions are not to be blindly adopted. No matter what they say, sometimes the best answer is to bite the bullet and go against convention to get things working. This, of course, largely depends on your scenario.
I'm reminded of a situation where days were spent re-organizing code to make the appropriate fix "the right way", when a simple GO TO would have worked great and only taken a couple of minutes to implement. In the end, a bunch of bugs were created because code was changed that did not need to be changed. Am I a fan of GO TO statements? Hell no! But if using one prevents a months worth of headaches, then there is no question.
I don't see any problem with that as long as the functionality or naming does not override what is already there. I know of some that modify the string prototype for Trim functions.
http://www.somacon.com/p355.php
What is funny, C# now has what's called an Extension Method which effectively does the same thing.
Not as itself, but the Ajax library makers might have problems if they cannot rely on the builtin types and their properties. So you could break code that relies on certain behaviour.
I've heard that it's not a good idea to make elements global in JavaScript. I don't understand why. Is it something IE can't handle?
For example:
div = getElementById('topbar');
I don't think that's an implementation issue, but more a good vs bad practice issue. Usually global * is bad practice and should be avoided (global variables and so on) since you never really know how the scope of the project will evolve and how your file will be included.
I'm not a big JS freak so I won't be able to give you the specifics on exactly why JS events are bad but Christian Heilmann talks about JS best practices here, you could take a look. Also try googling "JS best practices"
Edit: Wikipedia about global variables, that could also apply to your problem :
[global variables] are usually
considered bad practice precisely
because of their nonlocality: a global
variable can potentially be modified
from anywhere, (unless they reside in
protected memory) and any part of the
program may depend on it. A global
variable therefore has an unlimited
potential for creating mutual
dependencies, and adding mutual
dependencies increases complexity. See
Action at a distance. However, in a
few cases, global variables can be
suitable for use. For example, they
can be used to avoid having to pass
frequently-used variables continuously
throughout several functions.
via http://en.wikipedia.org/wiki/Global_variable
Is it something IE can't handle?
No it is not an IE thing. You can never assume that your code will be the only script used in the document. So it is important that you make sure your code does not have global function or variable names that other scripts can override.
Refer to Play Well With Others for examples.
I assume by "events" you mean the event-handling JavaScript (functions).
In general, it's bad to use more than one global variable in JS. (It's impossible not to use at least one if you're storing any data for future use.) That's because it runs into the same problem as all namespacing tries to solve - what if you wrote a method doSomething() and someone else wrote a method called doSomething()?
The best way to get around this is to make a global variable that is an object to hold all of your data and functions. For example:
var MyStuff = {};
MyStuff.counter = 0;
MyStuff.eventHandler = function() { ... };
MyStuff.doSomething = function() { ... };
// Later, when you want to call doSomething()...
MyStuff.doSomething();
This way, you're minimally polluting the global namespace; you only need worry that someone else uses your global variable.
Of course, none of this is a problem if your code will never play with anyone else's... but this sort of thinking will bite you in the ass later if you ever do end up using someone else's code. As long as everyone plays nice in terms of JS global names, all code can get along.
There shouldn't be any problem using global variables in your code as long as you are wrapping them inside a uniqe namespase/object (to avoid collision with scripts that are not yours)
the main adventage of using global variable in javascript derives from the fact that javascript is not a strong type language. there for, if you pass somes complex objects as arguments to a function, you will probebly lose all the intellisence for those objects (inside the function scope.)
while using global objects insteads, will preserve that intellisence.
I personally find that very usfull and it certainly have place in my code.
(of course, one should alwayse make the right balance between locales and globals variables)