JavaScript Garden(bonsaiden.github.com) |
JavaScript Garden(bonsaiden.github.com) |
One quibble: In the "common pitfalls" section regarding the "this" object, they say that locally-defined functions within other functions never have any practical use. I might disagree: with a little coaxing, you can convince locally variables inside the constructor (both functions and other variables) to serve as private properties of an object; this is the only technique I know that allows for private properties.
(I haven't actually done this in code that has been maintained/used anywhere, I just did it as an experiment and filed it away as a "that's cool" for future reference)
Edit: Here is an example of what I'm talking about: https://gist.github.com/866103
Might also come in handy if you are into functional programming with Javascript.
Since all functions are objects in JS, you can create a function with some internal (private) functions and properties than return a object with some publicly accessible functions. A basic example:
https://gist.github.com/866343
Closure gives you a really powerful structure that lets you encapsulate your code and then you don't have to use this and risk clobbering the global window object :)
1. If you use the "new" keyword, and don't execute the function. "x = new foo()". X becomes an "object". "foo()" is behaving like a class. You got to define the properties and methods of this class with the "this" keyword. Once you create your object with the "new" keyword, these variables got assigned to the object. And better, you can access them with the prototype.
2. If you execute the function in your code, that is you put "foo()": Open your FireFox with FireBug and notice two new global variables in the Windows object "get_my_private" and "set_my_private".
So it depends on the usage. "this" insides of a function is useful, if your intent is to use the function as a class. If not, it's dangerous, as the variables becomes global and may interfere with other variables.
function Foo(){
if (this == window) throw "USE NEW!";
// continue with object creation
}
Or use the standard practice of having class-creating function names capitalized, and let people know to follow it. function Podcast() {
if(false === (this instanceof Podcast)) {
return new Podcast();
}
// other code
} Bar.prototype = new Foo();
Then, Bar.prototype.constructor == Foo()So when you create a new instance of Bar, it's constructor still appears to be Foo even though it really isn't. Setting the prototype.constructor fixes that.
A bit controversial, don't you think?
If it's in a shared library, it is probably nicer to avoid. For instance, if you override a function on a native prototype, you might be overwriting some future function that browsers will implement. I've seen this done with Array.map for instance.
Sorry, but blanket statements like that are complete B.S. It all depends on context; it makes me dubious of the rest of this article if they can get away with statements like this.
Number.prototype.times=function(fn){
for(i=0;i<this;i++){ fn(i); }
}
3..times(alert)I'd add under setTimeout and setInterval that anything below 8ms may not work as expected across different browsers/hardware. Even setting 1ms to indicate "as soon as possible" may not occur as expected when repeatedly called.
also: the font size is a little small for my eyes in the code boxes - I can fix it of course with stylish but maybe that can be addressed directly on the site
Under “The evil eval”, it concludes that you should never use eval simply because it sometimes executes in global scope. That does not seem like an obvious conclusion to me. Yes, it’s a mistake to use it on user input, but that is easily avoided. I think the site should give an example of a situation where you think you need eval, the problems eval necessarily brings in that case, and how to write that without eval. Otherwise, I don’t trust that the site writer has actually explored why people use eval or what eval might be able to provide that nothing else can.
Also, under “Automatic semicolon insertion”, the site does not mention the alternative to using semicolons everywhere, which is not using semicolons but remembering to put a semicolon before each line starting with parentheses. That is a valid alternate practice, and the site ignores the possibility without even discussing its problems.
The fact that each of those two sections contain grammar mistakes (comma splices) also signals a lack of attention to detail.
if(!console)
instead of if(!window.console) or if( typeof console === 'undefined' )When the document scrolls it compares the scroll position to the stored offset positions.
If an article is close enough to the scroll offset it's highlighted.
It's really not that controversial.
If however, you are building a site or web app (like the majority of Javascript developers, I would assume), then the benefits of extending prototypes within your app can provide great advantages and keep your code much cleaner.
So again, I am not saying don't extend, and I am not saying extend, I am simply saying, that I agree that one should err on the side of caution and asses the situation for which they are coding for and make a decision regarding those circumstances. Simply saying a best practice is to 'never' do it to me is quite short sighted and is not properly educating new developers on how to write good Javascript.
For the record, I have often extended natives within my applications, and have never once had a conflict.
The assumption here is that you're never going to use any 3rd party code. Sure, a lot of libraries are forgiving of extended natives, but certainly not all JavaScript code is (especially code written before the hasOwnProperty method existed).
> For the record, I have often extended natives within my applications, and have never once had a conflict.
I have as well, it seems like a much more common practice in the past than now. I did, however, have conflicts with code (a date popup script, for example) that also extended natives. Now neither my own code, nor later versions of that exact script, extend natives anymore. I don't think the advantages are really all that great to warrant messing with them.
Also, my guide isn't even need the controversity of some of the statements that Crockford has made ;) In the end it's all advice, I'm not forcing you to write code this way.
In fact, I like it when people question the stuff I write, the worst thing that can happen is that people pick one book/guide whatever and just follow it 100% without ever thinking on their own.
The argument that you are giving for internal application development is akin to saying, well shit, someone could set your global namespace to null, so now what? Stop namespacing?
The better solution is don't use a crappy plugin. I prefer to write clean, maintainable, easy to read code with great abstractions, which would mean I refuse to use a shitty library and would opt instead to rewrite it myself or find a new one that does it right.
Again, I really don't see this as an issue, because extending native prototypes is one of Javascript's more powerful utilities.