Now let me post a couple of code snippets that are lying around here already for a while. For the uber geeks out there you might yawn seeing them, but there are a lot of people who are searching for this stuff over and over, including myself. So let me post some small useful snippets that have went through my fingers lately.
Reading on, you will see snippets that help you with 1) detecting if a variable is a real array 2) how to convert it into a proper array 3) how to mimic a x = [3..25] kinda thing that other languages offer 4) how to easily pad a string with leading chararacter (i.e. zeros) and finally 5) how to create a unique function for arrays.
There are a lot of ways to check for a variable being an array, but the safest one and also most promoted and secure one is
1 | Object.prototype.toString.call(arg) == '[object Array]'; |
Some examples from the console demostrate well how to use it and that it really works :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> arr = 1 // That's a simple integer, of course. >>> Object.prototype.toString.call(arr) == '[object Array]'; false >>> arr = '1' // Just a string. >>> Object.prototype.toString.call(arr) == '[object Array]'; false >>> arr = '[1,2,3]' // Also a string. >>> Object.prototype.toString.call(arr) == '[object Array]'; false >>> arr = {x:1, y:2} // That's an object, no array either! >>> Object.prototype.toString.call(arr) == '[object Array]'; false >>> arr = [1,2,3] // An array, so it should be true. >>> Object.prototype.toString.call(arr) == '[object Array]'; true |
One of the pains JavaScript developers have to fight with which will get solved with future versions (fortunately) is that the arguments object looks like an array, e.g. it has the property length but you can’t work with it as if it was an array, e.g. here:
1 2 3 4 5 6 | >>> function f() { console.log(arguments.length) } >>> f(1,2,3) 3 // arguments.length works >>> function f() { arguments.slice() } >>> f(1,2) TypeError: arguments.slice is not a function // slice() is not available :( |
But their is a workaround until the language handles it. It is
1 2 3 4 | >>> function f() { var realArray = [].slice.call(arguments, 0); console.log(realArray.slice()) } >>> f(1,2,3) [1, 2, 3] // slice throws no error, hurray! |
Sometimes you need just a plain array with a set of numbers of a certain range, i.e. when generating a set of chars, like all upper case characters. But there is no “x = [1..5]” in JavaScript yet(!). But I needed one, and it’s easy to make one, as you can see:
1 2 3 4 5 6 7 8 9 | >> var chars = []; >>> for (var i=65; chars.push(i) && i<90; i++){}; [65, 66, 67, 68, 69, 70, ... 85, 86, 87, 88, 89, 90] >>> // Let's print them. >>> chars.forEach(function(c){ console.log(String.fromCharCode(c)) }) A ... Z |
Sometimes you want to pad numbers with zeros e.g. to align them on the console. Here is how I did that:
1 2 3 4 5 6 | >>> ('00' + 3).slice(-3) "003" >>> ('00' + 42).slice(-3) "042" >>> ('00' + 103).slice(-3) "103" |
The -3 is the number*-1 of characters my string shall have in the end. I am adding two zeros at the beginning, because I am sure that a number is never an empty string. And after the string concatenation I just take only the last three characters. Simple but works nice without any kind of IFs or complex logic.
PHP has a hell lot of array functions, a bit wild – yeah. But sometimes you wished you had them all too. A unique() function is one of those that I just needed lately again, so here is a simple one:
1 2 3 4 5 6 7 8 9 10 | >>> function unique(arrayData){ return arrayData.filter(function(val, idx, arr){ return arr.slice(0, idx).indexOf(val)==-1 }) } >>> unique([1,2,3,4,1,2,1,3]) [1, 2, 3, 4] >>> unique([1,2,3,4,1,2,1,3,5]) [1, 2, 3, 4, 5] >>> unique(['a', 'a', 'b', 'B']) ["a", "b", "B"] |
So have fun, hope something was useful.
Comments
2
3
4
5
6
7
8
9
10
11
var parts = input.split('..'),
start = +parts[0],
end = +parts[1],
counter = start,
output = [];
for (; output.push(counter) && counter < end; counter++);
return output;
}
range('3..25'); // [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
January 19, 2012 — 09:09 am
Mathias Bynens
Sweet
January 19, 2012 — 09:38 am
Wolfram Kriesing
The argument to array conversion is pretty neat, didn’t know about it till now (though, I don’t use arguments often).
Jeremy Askenas made “stdlib” for JavaScript, called underscore.js (http://documentcloud.github.com/underscore) which combines many snippets and helper methods. You might wanna take a look at it.
January 19, 2012 — 09:41 am
Sebastian Slomski
Shorter Range:
2
3
4
for (var r = []; start < stop; r.push(start++));
return r;
}
Idiomatic? use of map and forEach:
2
3
.map(String.fromCharCode, String)
.forEach(console.log, console);
January 19, 2012 — 09:46 am
david
@sebastian, yeah nice!
@david love it
January 19, 2012 — 09:50 am
Wolfram Kriesing
I generally use (which I stole from Ben Nadel):
argsArray = Array.apply(null, arguments);
Is this wrong?
January 19, 2012 — 05:30 pm
Alexander Mackay-Austin
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
return Array(end - start + 1).join(' ').split(' ').map(function(s,i){ return i + start });
}
// numbers and strings, O(n)
function primitiveUnique(arr){
return Object.keys(arr.reduce(function(r, s){
return r[s] = 1, r;
}, {}));
}
// all value types
function unique(arr){
return arr.filter(function(s, i, a){
return i === a.lastIndexOf(s);
});
}
function isType(compare){
if (typeof compare === 'string' && /^\w+$/.test(compare)) {
compare = '[object ' + compare + ']';
} else {
compare = Object.prototype.toString.call(compare);
}
return isType[compare] || (isType[compare] = function(o){
return Object.prototype.toString.call(o) === compare;
});
}
var isArray = isType([]); // same as isType('Array')
var isArguments = isType('Arguments');
var callbind = Function.prototype.call.bind.bind(Function.prototype.call);
var applybind = Function.prototype.call.bind.bind(Function.prototype.apply);
var slice = callbind(Array.prototype.slice);
var pushall = applybind(Array.prototype.apply);
var toClass = callbind(Object.prototype.toString);
function someFn(){ var args = slice(arguments) }
var arr = [];
function anotherFn(){ pushall(arr, arguments) }
January 20, 2012 — 05:21 pm
Brandon Benvie
Interesting speed compare of the different range() functions: http://jsperf.com/range-function in short David’s version is the fastest.
January 22, 2012 — 04:52 pm
Wolfram Kriesing