JavaScript hacks explained
From: http://blog.mdnbar.com/javascript-common-tricks
There are several JavaScript tricks that are used widely by experienced programmers. Many of them may not be instantly obvious, especially for beginners. These tricks use language features not by their direct purpose, but rather by their side-effect to achieve goals, that can’t be achieved by default language means. Here I made a little compilation of such tricks with explanation.
You should understand that most of these tricks are rather hacks and not something you should use in your daily development. The purpose of that article is to explain how they work, not to push to use them.
Using !! to convert value into a boolean
Everything in JavaScript can be interpreted either as [truthy or falsy](’http://www.sitepoint.com/javascript-truthy-falsy/’). This means that when you put object into an if expression, it will either let you go by true-branch (i.e. it’s ‘truthy’) of by false branch('falsy’).
0, false, "", null, undefined, NaN are all falsy, every other object is truthy. Sometimes you’d like to convert an object to a plain boolean value. To do this you can use double negation !!.
Another side of that coin is that instead of if (x == "test") you can simply write if (x). In case x is empty (hence falsy) it will run else block.
Converting string into a number with +str
In JavaScript + is a unary operator that returns a numeric representation of operand or NaN if not applicable. Sometimes you can enforce code (see underscorejs sources) such as x === +x, which is thus just checking whether x is numeric.
This one is not obvious at all. Normally you’d want to use parseFloat and parseInt(x, 10) for parsing numbers.
Providing default value with ||
In JavaScript || is an example of short-circuit evaluation, which is also commonly used in some other language. This operator will firstly evaluate expression on the left side, and then, if falsy, will proceed with on the right. In any case it will return first non-falsy result. Consider the following example
function setAge(age) {
this.age = age || 10
}
setAge();
We didn’t provide age, thus age || 10 will return 10, which is a nice way to provide some defaults values. In fact this is equivalent to
var x;
if (age) {
this.age = age;
} else {
this.age = 10;
}
The former is obviously more succinct and that’s why you will see it used everywhere.
Personally, I use that pattern a lot. I like its conciseness and clarity. Notice, however, that since 0 is falsy you won’t have an ability to set age to 0. Therefore, it might be a better (but slightly more verbose) solution to use something like this:
this.age = (typeof age !== "undefined") ? age : 10;
Using void 0 instead of undefined
Keyword void takes one argument and always return undefined. Why not to simply use undefined? Because in some browsers undefined is just a variable that can be reassigned, and the former gives us a higher level of confidence. Although you can find this being used in source code of some libraries, I would not recommend using it on the regular basis, since all EC5-compliant browsers don’t allow to rewrite undefined.
Encapsulation with (function() {...})() pattern
You’ll want to wrap your code into an anonymous function and then immediately call it, when you want some encapsulation. There are only two types of scopes in JavaScript (but look at ECMA6 block scopes): global scope and function scope. Everything you write goes into global scope, which is accessible from everywhere. This includes vars and function declarations. Normally you’d want to encapsulate most of the code somewhere inside of a function and expose to global scope only interface. And that’s where this pattern gets really handy. Consider the following:
(function() {
function div(a, b) {
return a / b;
}
function divBy5(x) {
return div(x, 5);
}
window.divBy5 = divBy5;
})()
div // => undefined
divBy5(10); // => 2
Among other hacks listed in this article this one is really harmless and you can and should use it in your code to prevent exposing some inner logic into the global scope.
In conclusion, I’d like to remind you that any code you write should be simple and clear to other programmers. And any natural constructions provided by language should be preferred to artificial ones.
Some of the problems, listed in that article are being solved in elegant way by ES6 standart (next version of JavaScript). For instance, you’ll probably won’t need the obscure age = age || 10 pattern in the future, since ES6 allows you to write default arguments in a better way:
function(age = 10) {
...
}
Another example, is (function() {...})() pattern, which you can leave in the past after EC6 modules get implemented by modern browsers.
There are several JavaScript tricks that are used widely by experienced programmers. Many of them may not be instantly obvious, especially for beginners. These tricks use language features not by their direct purpose, but rather by their side-effect to achieve goals, that can’t be achieved by default language means. Here I made a little compilation of such tricks with explanation.
You should understand that most of these tricks are rather hacks and not something you should use in your daily development. The purpose of that article is to explain how they work, not to push to use them.
Using !! to convert value into a boolean
Everything in JavaScript can be interpreted either as [truthy or falsy](’http://www.sitepoint.com/javascript-truthy-falsy/’). This means that when you put object into an if expression, it will either let you go by true-branch (i.e. it’s ‘truthy’) of by false branch('falsy’).
0, false, "", null, undefined, NaN are all falsy, every other object is truthy. Sometimes you’d like to convert an object to a plain boolean value. To do this you can use double negation !!.
Another side of that coin is that instead of if (x == "test") you can simply write if (x). In case x is empty (hence falsy) it will run else block.
Converting string into a number with +str
In JavaScript + is a unary operator that returns a numeric representation of operand or NaN if not applicable. Sometimes you can enforce code (see underscorejs sources) such as x === +x, which is thus just checking whether x is numeric.
This one is not obvious at all. Normally you’d want to use parseFloat and parseInt(x, 10) for parsing numbers.
Providing default value with ||
In JavaScript || is an example of short-circuit evaluation, which is also commonly used in some other language. This operator will firstly evaluate expression on the left side, and then, if falsy, will proceed with on the right. In any case it will return first non-falsy result. Consider the following example
function setAge(age) {
this.age = age || 10
}
setAge();
We didn’t provide age, thus age || 10 will return 10, which is a nice way to provide some defaults values. In fact this is equivalent to
var x;
if (age) {
this.age = age;
} else {
this.age = 10;
}
The former is obviously more succinct and that’s why you will see it used everywhere.
Personally, I use that pattern a lot. I like its conciseness and clarity. Notice, however, that since 0 is falsy you won’t have an ability to set age to 0. Therefore, it might be a better (but slightly more verbose) solution to use something like this:
this.age = (typeof age !== "undefined") ? age : 10;
Using void 0 instead of undefined
Keyword void takes one argument and always return undefined. Why not to simply use undefined? Because in some browsers undefined is just a variable that can be reassigned, and the former gives us a higher level of confidence. Although you can find this being used in source code of some libraries, I would not recommend using it on the regular basis, since all EC5-compliant browsers don’t allow to rewrite undefined.
Encapsulation with (function() {...})() pattern
You’ll want to wrap your code into an anonymous function and then immediately call it, when you want some encapsulation. There are only two types of scopes in JavaScript (but look at ECMA6 block scopes): global scope and function scope. Everything you write goes into global scope, which is accessible from everywhere. This includes vars and function declarations. Normally you’d want to encapsulate most of the code somewhere inside of a function and expose to global scope only interface. And that’s where this pattern gets really handy. Consider the following:
(function() {
function div(a, b) {
return a / b;
}
function divBy5(x) {
return div(x, 5);
}
window.divBy5 = divBy5;
})()
div // => undefined
divBy5(10); // => 2
Among other hacks listed in this article this one is really harmless and you can and should use it in your code to prevent exposing some inner logic into the global scope.
In conclusion, I’d like to remind you that any code you write should be simple and clear to other programmers. And any natural constructions provided by language should be preferred to artificial ones.
Some of the problems, listed in that article are being solved in elegant way by ES6 standart (next version of JavaScript). For instance, you’ll probably won’t need the obscure age = age || 10 pattern in the future, since ES6 allows you to write default arguments in a better way:
function(age = 10) {
...
}
Another example, is (function() {...})() pattern, which you can leave in the past after EC6 modules get implemented by modern browsers.
评论
发表评论