Javascript/jQuery "Gotchas" [closed]
开发者_如何学Python
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this questionWhat are some of the common Javascript and/or jQuery "gotchas" that you have seen or been tripped up by?
As an example, it was pointed out to me this morning that you have to be careful with the radix when doing parseInt()
, because if your string starts with a 0, the radix will default to 8.
Replacing .round()
/ .floor()
or .ceil()
with ~~
to cut away decimal places is pretty handsome.
Instead of
Math.floor(Math.random() * 100);
you do
~~(Math.random() * 100);
It's just shorter and has a better performance even!
The scope of 'this'
Consider the following example:
function myClass(message) {
this.message = message;
$('button').click(function(){
this.onClick();
});
}
myClass.prototype.onClick = function() {
alert(this.message);
}
Of course, line 3 does not work: this
works on a per-function basis, and the function defined on line 2 will have the selected button as this
instead of the instance of myClass. There's an even sneakier version:
function myClass(message) {
this.message = message;
$('button').click(this.onClick);
}
myClass.prototype.onClick = function() {
alert(this.message);
}
This calls the correct function, but this
would still be the button (because this
is determined by the caller, not by the fact that you're a member function). The correct solution is to use an intermediate variable, such as self
, to apply sane scoping rules to this
:
function myClass(message) {
this.message = message;
var self = this;
$('button').click(function() { self.onClick(); });
}
Type casting
[] == ![]
evaluates to true for obscure reasons
Arrays and Properties
The length
property only works for integer keys on arrays. For instance:
var a = []; // a.length == 0
a[0] = 'first'; // a.length == 1
a['1'] = 'second'; // a.length == 2
a['x'] = 'third'; // a.length == 2 <-- 'x' does not count
While on this topic, for( in )
works on arrays, but traverses all properties defined on the array. This means that your JavaScript code that uses for( in )
to iterate through arrays will suddenly stop working on certain browsers when you add ExtJS to your project, because ExtJS defines Array.prototype.filter
if it's not present (this is known as monkey patching). Since now filter
is a custom property of every array object, all your loops also iterate through it. Boom.
The clean way of iterating through an array is using length and an incrementing for loop. Or jQuery's $.each()
.
The biggest WTF that I have come across in Javascript must be String.replace
.
Take this code for example:
"An,example,of,a,comma,separated,sentence".replace(',', ' ');
This produces a sentence nicely separated by spaces instead, right?
To my utter surprise: no, it does not. It only replaces the first comma with a space, leaving the rest untouched. If you want to do an actual replace, you have to use .replace(/,/g, ' ')
.
Why the method is not called 'replaceFirst' is anyone's guess.
i would recomend to read entire http://wtfjs.com/
The return
statement must have a value immediately following it, or at least starting on the same line:
return 4; // returns 4
return {}; // returns an empty object
return { // returns an empty object
};
return // returns undefined
{
};
Ajax gets/posts to a static URI can get cached by IE. So you need to append an ever changing parameter, a quick and easy way is to append new Date().getTime()
Douglas Crockford's book JavaScript: The Good Parts is an excellent read about the topic. There are also the bad and awful parts of Javascript in it :)
A very good article was recently by Elijah Manor on his blog, Enterprise jQuery. It's written on Javascript "gotchas" for C# developers. It's a part series and there are a number of good points that will also "get" individuals familiar with other languages.
Check it out here: How Good C# Habits can Encourage Bad JavaScript Habits.
Variable scope and loop variables is definitely a "gotcha". This happens a lot when assigning event handlers in a loop:
var lis= document.getElementsByTagName('li'),
imgs = document.getElementsByTagName('img');
for (i = 0; i < elements.length; i++)
{
elements[i].onclick = function() {
imgs[i].src = elements[i].innerHTML;
}
}
At the time of execution, imgs[i]
will be undefined, throwing an error when trying to access imgs[i].src
. The same for elements[i]
and its innerHTML
.
Implied globals are a big one:
var x = 12, y = 14;
function addOne(num)
{
x = num + 1; // since this is not declared with 'var', it is implied global
return x;
}
alert(addOne(y)); // alerts '15'
alert(addOne(x)); // alerts '16'
It's a simple, and unrealistic example, but demonstrates the problem nicely.
Javascript
parseInt('0aaa') //still returns 0
parseFloat('0.aaa') //still returns 0
This ones more of an oops factor. When writing a switch statement, I have been known to forget to place a break in the statement, which causes issues.
var myvar = '1'
switch (myvar) {
case '1':
alert(myvar);
case '2':
alert(myvar);
break;
}
Because I forgot the break in the case '1'
you will receive the alert twice.
精彩评论