Consider the following use case for creating two classes Point and YAxisPoint:
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return `${this.x},${this.y}`;
};
var p = new Point(1, 2);
var YAxisPoint = Point.bind(null, 0);
var axisPoint = new YAxisPoint(5);
console.log(p.toString()); // '1,2'
console.log(axisPoint.toString()); // '0,5'
Executing this code in the browser yields the correct results. Now let's say I want to override the toString function for YAxisPoint constructor:
YAxisPoint.prototype.toString = function() { return 'override'; }
var newAxisPoint = new YAxisPoint(5);
console.log(newAxisPoint.toString()); // 'override'
Executing this code in the browser yields:
Uncaught TypeError: Cannot set property 'toString' of undefined
Question 1
Why the prototype for YAxisPoint is undefined?
I really don't get it. If I add the following polyfill it works as expected.
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
Question 2
Is there a bug in the browser implementations for bind? I tried this in Opera, Safari, Chrome, and Firefox and they all have the same problem.
Here is a link to a code that you can run to test.
The polyfill in this sandbox is commented out. You can uncomment that to validate.