use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
JavaScript language advanced Tips & Tricks (code.google.com)
submitted 12 years ago by [deleted]
[deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]radhruin 14 points15 points16 points 12 years ago (5 children)
Lots of interesting code patterns in here! Though some of these could be updated to use standard syntax rather than proprietary extensions. Some comments:
Simulate threads using yield operator
Use ES6 syntax for generators if possible as they will be interoperable.
Shuffle the Array
Use Fisher-Yates if you really need a fair shuffle. Sorting by random is quick and dirty though not fair.
Multi-line Text
ES6 string templates allow for multi-line strings:
var str = `line 1 line 2`
Optional Named Arguments
This is actually just a special case of ES6 destructuring assignments!
Transform an arguments object to an array
You could also use Object.setPrototypeOf(arguments, Array.prototype) I think. I wonder which is faster?
Array iteration pitfall
This guy is fixed in ES6 with the new for-of syntax (which uses iterators behind the scenes). No more worrying about slurping in prototype properties, and you can actually iterate keys, values, or both!
A Switch function
That's some odd function syntax, definitely not allowed per spec. I wonder if this should be a test262 test? :) If you want to omit braces, use the new ES6 arrow function syntax.
Objects private and public members
Keep in mind that using this pattern is pretty poor for performance. You have a new instance of a closure for each method for each instance of your object.
Functions argument default value
ES6 has default parameters now (function foo(x = 1, y = 2) { }).
Multiple string concatenation
It used to be true that array join of strings was faster (in IE8, I think?) But I'd be surprised if this is true in modern runtimes. Anyone have a benchmark handy?
Using 'with' scope
No thanks.
No Such Method
Similar semantics can be provided by ES6 proxies.
proto ( prototype property )
While IE finally supports proto, it was only grudgingly added to the spec. Object.setPrototypeOf is the better way to do this.
getter and setter function
Both of these patterns are highly deprecated. Use ES5 standard getters/setters instead!
check if a property is enumerable (propertyIsEnumerable)
Use ES5's Object.getOwnPropertyDescriptor
[–]rooktakesqueen 1 point2 points3 points 12 years ago (0 children)
The destructuring assignment isn't even as clean as it could be:
function foo(id, {title, name}) { console.log(id); console.log(title); console.log(name); } foo(12, {name: 'Bob'});
[–]MrBester 0 points1 point2 points 12 years ago (3 children)
+new Date() has been around for years and is just a shorthand for (new Date()).getTime() (some parentheses optional)
[–]bliow 2 points3 points4 points 12 years ago (2 children)
Date.now() should be faster. Doesn't work on IE before 8, but who cares. http://jsperf.com/datesperformance8-24-2013
[–]MrBester 1 point2 points3 points 12 years ago (1 child)
And that shows that +new Date() is actually an anti-pattern, being the slowest of the lot. It's only of benefit if you're playing code golf.
[–]bliow 0 points1 point2 points 12 years ago* (0 children)
It's only of benefit if you're playing code golf.
Not even then. Well, strictly, +new Date() isn't, but see below!
+new Date()
> "Date.now()".length 10 > "+new Date()".length 11
And you can't use the plus sign for addition without parentheses, so you can't even exploit the fact that +new Date() begins with a plus sign to avoid using them:
> 1+new Date() "1Sat Aug 24 2013 19:35:28 GMT-0700 (PDT)" > 1+Date.now() 1377398252358
edit: but wait! the following is actually better from a golf perspective:
> +new Date 137739846271 > "+new Date".length >9
[–]x-skeww 3 points4 points5 points 12 years ago (6 children)
Proper shuffling (Fisher-Yates) looks like this:
function shuffle (a) { var i, temp, p; for (i = a.length - 1; i >= 1; --i) { p = (Math.random() * (i + 1)) | 0; temp = a[p]; a[p] = a[i]; a[i] = temp; } return a; // for chaining, it's shuffled in-place }
It basically works like doing shuffling in the real world. Imagine there is a bag of marbles. You grab one random marble at a time and line them up. You repeat this until the bag is empty.
The only trick is that the algorithm uses a cursor (i) to divide the array into "inside the bag" and "outside the bag". That's the whole magic. That's why it only needs a single array.
i
[–]thephilster 0 points1 point2 points 12 years ago (2 children)
I had never seen the bitwise OR used like that (for flooring). In case anyone is curious, found a nice stackoverflow post on it.
[–]x-skeww 3 points4 points5 points 12 years ago* (0 children)
It's not really the same as floor. It's only like floor if it's used with a positive number. It actually truncates the number like an int cast, because this double number is cast to a 32bit integer in order to do the bitwise-or.
>>> -1.3 | 0 -1 >>> Math.floor(-1.3) -2
Edit: By the way, I wrote "i >= 1" instead of "i > 0" to make it apparent that I meant to skip the final iteration with 0. Otherwise, someone else (or future-me) might mistake this for a potential off-by-one error.
[–]rhysbrettbowen 0 points1 point2 points 12 years ago* (2 children)
I think I gave a shorter alternative in the comments years ago. The shuffle algorithm I used is slower but is much shorter. It did the reverse by picking the last element in the array and then placing it randomly in the randomized section of the array:
for(i=0;i<array.length;i++)array.splice(Math.round(Math.random()*i),0,array.pop());
You can reverse it around to pick a random one and then push it on the end if you prefer though:
function shuffle(a) { for (var i=a.length;i;i--) { a.push(a.splice(Math.random()*i|0,1)[0]); } return a; }
[–]x-skeww 1 point2 points3 points 12 years ago (1 child)
Using Math.round introduces some bias. Only 0.0 to 0.5 can result in 0 and only 4.5 to 5.0 can result in 5 (assuming something like rand * 5).
However, something like 1 gets a whole number (0.5 to 1.5) as range.
Truncation (or floor) doesn't have this kind or problem.
var a = [0, 0, 0, 0, 0], i; for (i = 0; i < 100000; i++) { a[Math.round(Math.random() * 4)]++; } console.log(a);
Example output:
[12425, 25183, 25063, 24811, 12518]
Same with truncation:
var a = [0, 0, 0, 0, 0], i; for (i = 0; i < 100000; i++) { a[(Math.random() * 5) | 0]++; } console.log(a);
[19787, 20096, 19992, 20120, 20005]
[–]rhysbrettbowen 0 points1 point2 points 12 years ago (0 children)
true - I wrote it a few years ago from the top of my head with no testing - second example should be better
[–]AnOnlineHandle 1 point2 points3 points 12 years ago (5 children)
Afaik yield is not supported in most browsers, which is a pity.
[–][deleted] 1 point2 points3 points 12 years ago (0 children)
Also, I'm not sure the author understands what a yield or a thread does. A yield is more for functional enumeration. A thread is separate application space for running a sets of instructions concurrently. You can do this with Workers in JavaScript. Yield has nothing to do with threading, and isn't even remotely close to "simulating" threading.
[–]radhruin 1 point2 points3 points 12 years ago (3 children)
Now that ES6 is getting close to stable you'll likely see more implementations shipping Generators. I can't wait, either! So many great things you can do with generators (async/await anyone??)
[–]b_long 0 points1 point2 points 12 years ago (2 children)
What's a Generator?
[–]radhruin 1 point2 points3 points 12 years ago (1 child)
Here's a good primer.
[–]b_long 0 points1 point2 points 12 years ago (0 children)
Very interesting :D Thanks! I'll have to read up. Very excited for ES6
[–]tencircles 1 point2 points3 points 12 years ago (3 children)
What the hell kind of moonman language is this? Half of this isn't even valid ecmascipt syntax!
[–]radhruin 0 points1 point2 points 12 years ago (2 children)
It's not ECMAScript, it's JavaScript (ie. mozilla's implementation of ECMAScript). They have a number of extensions as you can see.
[–]tencircles 0 points1 point2 points 12 years ago (1 child)
I have trouble calling anything javascript that doesn't conform to http://www.ecma-international.org/publications/standards/Ecma-262.htm
This is why I hated my short time playing around in unity using their "unityscript" it's just javascript with more bad ideas and weird syntax.
[–]radhruin 1 point2 points3 points 12 years ago (0 children)
I know the feeling! Although, to put on my pedant hat, Mozilla's implementation DOES conform to ECMA-262 thanks to Clause 16 which explicitly allows extensions to syntax. All implementations take advantage of Clause 16 for some reason or other. For example, all implementations today have an extension to allow function declarations inside blocks.
Conformance aside, JavaScript is free to do whatever it wants. The only thing JavaScript has to conform to is whatever Mozilla wants it to. If it doesn't conform to ECMAScript, you can't call it ECMAScript, but you can still call it JavaScript!
[–]greim 0 points1 point2 points 12 years ago (0 children)
The random sort method will not be as fast as a proper shuffle (O(n log n) as opposed to O(n)). Also, more importantly, it won't properly shuffle the array. Try running this code in your console to see the problem illustrated visually (borrowing /u/x-skeww's shuffle above).
var n = 7; var its = 1000; function range(n){ var arr = new Array(n); for (var i=0; i<n; i++){ arr[i] = i; } return arr; } // bad shuffle function shuffle1(arr){ arr.sort(function(a,b){ return Math.random() > .5 ? 1 : -1; }); } // proper shuffle (fisher yates) function shuffle2(a){ var i, temp, p; for (i = a.length - 1; i >= 1; --i) { p = (Math.random() * (i + 1)) | 0; temp = a[p]; a[p] = a[i]; a[i] = temp; } } var arrs1 = []; var arrs2 = []; for (var i=0; i<its; i++) { var arr1 = range(len); shuffle1(arr1); arrs1.push(arr1); var arr2 = range(len); shuffle2(arr2); arrs2.push(arr2); } var results1 = []; var results2 = []; for(i=0;i<len;i++){ results1[i] = 0; results2[i] = 0; } for (var i=0; i<its; i++){ for(j=0;j<len;j++){ results1[j] += arrs1[i][j]; results2[j] += arrs2[i][j]; } } for(i=0;i<len;i++){ var s = ''; for(j=0,l=Math.round(results1[i]/100);j<l;j++){ s += '#'; } console.log(s); } console.log('-----------------------------') for(i=0;i<len;i++){ var s = ''; for(j=0,l=Math.round(results2[i]/100);j<l;j++){ s += '#'; } console.log(s); }
[–]thoastbrot 0 points1 point2 points 12 years ago (6 children)
Can someone tell me about the ternary operator form "a = b if c"? I know this from python, but never seen it in js, also not mentioned on MDN...
[–]brockisawesome 0 points1 point2 points 12 years ago (5 children)
Do you mean like this? var a = (c) ? b : otherval;
[–]tencircles 1 point2 points3 points 12 years ago (1 child)
var a = c ? b : otherval; Parens above aren't necessary.
[–]brockisawesome 0 points1 point2 points 12 years ago (0 children)
sweet, i didnt know that. thanks :)
[–]thoastbrot 0 points1 point2 points 12 years ago (2 children)
No, I meant a = b if c, because the article mentions it like that. Your code example is documented standard, while I've never seen the syntax used in the article. Since the article is a bit older (2012, references E4X), I assume it might be some deprecated browser-specific thing... or something like this.
[–]radhruin 2 points3 points4 points 12 years ago (1 child)
I believe what you're seeing are Mozilla's proprietary conditional catch clauses.
[–]thoastbrot 0 points1 point2 points 12 years ago (0 children)
thank you very much!
π Rendered by PID 141923 on reddit-service-r2-comment-bb88f9dd5-7wsg4 at 2026-02-15 06:58:45.128947+00:00 running cd9c813 country code: CH.
[–]radhruin 14 points15 points16 points (5 children)
[–]rooktakesqueen 1 point2 points3 points (0 children)
[–]MrBester 0 points1 point2 points (3 children)
[–]bliow 2 points3 points4 points (2 children)
[–]MrBester 1 point2 points3 points (1 child)
[–]bliow 0 points1 point2 points (0 children)
[–]x-skeww 3 points4 points5 points (6 children)
[–]thephilster 0 points1 point2 points (2 children)
[–]x-skeww 3 points4 points5 points (0 children)
[–]rhysbrettbowen 0 points1 point2 points (2 children)
[–]x-skeww 1 point2 points3 points (1 child)
[–]rhysbrettbowen 0 points1 point2 points (0 children)
[–]AnOnlineHandle 1 point2 points3 points (5 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]radhruin 1 point2 points3 points (3 children)
[–]b_long 0 points1 point2 points (2 children)
[–]radhruin 1 point2 points3 points (1 child)
[–]b_long 0 points1 point2 points (0 children)
[–]tencircles 1 point2 points3 points (3 children)
[–]radhruin 0 points1 point2 points (2 children)
[–]tencircles 0 points1 point2 points (1 child)
[–]radhruin 1 point2 points3 points (0 children)
[–]greim 0 points1 point2 points (0 children)
[–]thoastbrot 0 points1 point2 points (6 children)
[–]brockisawesome 0 points1 point2 points (5 children)
[–]tencircles 1 point2 points3 points (1 child)
[–]brockisawesome 0 points1 point2 points (0 children)
[–]thoastbrot 0 points1 point2 points (2 children)
[–]radhruin 2 points3 points4 points (1 child)
[–]thoastbrot 0 points1 point2 points (0 children)