I noticed something weird while reviewing this mergesort implementation on Code Review…
/************************************************************
* Mergesort implementation
***********************************************************/
function sort(array) {
var len = array.length;
var middle = Math.floor(len*0.5);
var left = array.slice(0,middle);
var right = array.slice(middle, len);
if (len == 1) {
return array;
} else {
}
return merge(sort(left), sort(right));
}
function merge(left, right) {
var a = left.length;
var b = right.length;
if (a > 0 && b > 0) {
if (left[0] > right[0]) {
return [].concat(left[0], merge(left.slice(1,a), right));
} else {
return [].concat(right[0], merge(right.slice(1,b), left));
}
} else if (a == 0) {
return right;
} else of (b == 0)
return left;
}
/************************************************************
* Demonstration
***********************************************************/
function doSort() {
var array = document.getElementById('in').value.split(/[, ]+/).map(function(e) {
return parseInt(e);
});
var sorted = sort(array);
document.getElementById('out').value = sorted;
}
function generateRandom(len) {
var array = [];
for (var i = 0; i < len; i++) {
array.push(Math.round(Math.random() * 100));
}
document.getElementById('in').value = array;
};
generateRandom(20);
<button onclick="generateRandom(20)">⬇︎ Generate random numbers ⬇︎</button>
<div><input id="in" size="80"></div>
<button onclick="doSort()">⬇︎ Sort ⬇︎</button>
<div><input id="out" size="80" disabled></div>
The last conditional branch is else of
rather than else if
. Normally, else of
should result in a syntax error. Yet, no matter how hard I try, I can't trigger the syntax error — it always successfully returns an array sorted in descending order!
I know, else of (b == 0)
could just be replaced by else
, but still, I want to know: How could this code possibly work?
This works because of a combination of 2 "bad things" about Javascript: skipping braces in block statements that contain only a single statement, and semicolon insertion.
Your if
statement, properly braced, should look like this:
if (a > 0 && b > 0) {
if (left[0] > right[0]) {
return [].concat(left[0], merge(left.slice(1,a), right));
} else {
return [].concat(right[0], merge(right.slice(1,b), left));
}
} else if (a == 0) {
return right;
} else of (b == 0) {
return left;
}
but, because of the missing braces and semicolon insertion, Javascript is seeing/parsing it like this:
if (a > 0 && b > 0) {
if (left[0] > right[0]) {
return [].concat(left[0], merge(left.slice(1,a), right));
} else {
return [].concat(right[0], merge(right.slice(1,b), left));
}
} else if (a == 0) {
return right;
} else {
of(b == 0);
}
return left;
If you always pass in legitimate left
and right
arrays then this last else
branch is never reached, hence why you haven't seen an exception.
If you pass in an empty right
array, it will reach the last branch and throw of is not a function
:
merge([10, 20, 30], []);
Any respectable coding standard should explicitly require these 2 "features" of Javascript never be used... but that's just one opinion.
of
is a keyword in ES6, used for iterating over objects..
but in this case the of
is behaving as function not keyword..
The function code never goes to else of (b == 0) return left;
part.. so compiler is not throw ReferenceError: of is not defined
if you will change of
keyword into another word like else often(b==0)....
then also code work
when you send right side empty then code will throw error ReferenceError: of is not defined
, so finally this is only typo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With