Необходимо убедиться, что
- (1) связанная функция может использоваться в качестве конструктора, игнорируя привязку.(следовательно, проверка
instanceof
) - (2) В то же время вы хотите убедиться, что
new g()
наследуется от цепочки прототипов f
.(отсюда .prototype = new fNop
часть)
Пример:
function f() {
this.foo = 'bar';
}
f.prototype = {
baz: 'yay!'
};
var g = f.bind({});
var o = new g();
console.log(o.foo); // 'bar' - (1)
console.log(o.baz); // 'yay!' - (2)
В тот момент, когда вы вызываете new g()
, функция fBound
вызывается как производитель с брендомновый объектный объект (this
), который является экземпляром fNop
.
Редактировать:
Стандарт ECMAScript5 определяет сложный алгоритм для функций привязки.Среди прочего, следующие утверждения должны выполняться:
var DateJan2042 = Date.bind(null, 2042, 0);
/*1*/ console.assert(Function.prototype.bind.length == 1, 'bind should have a length of 1');
/*2*/ console.assert(typeof DateJan2042 == 'function', 'bind() should return a function');
/*3*/ console.assert(!DateJan2042.hasOwnProperty('prototype'), 'Bound function must not have a prototype');
/*4*/ console.assert(DateJan2042.length == Math.max(Date.length - 2, 0), 'Bound function should have a proper length');
/*5*/ console.assert(typeof DateJan2042() == 'string', 'Function call should return a string');
/*6*/ console.assert({}.toString.call(new DateJan2042()).indexOf('Date') != -1, 'Constructor call should return a new Date object');
/*7*/ console.assert(new DateJan2042() instanceof DateJan2042, 'Instanceof check should pass for constructor\'s return value');
/*8*/ console.assert((new DateJan2042()).getMonth() == 0, 'Constructor should be called with bound arguments');
/*9*/ console.assert((new DateJan2042(1)).getDate() == 1, 'Constructor should take additional arguments');
/*10*/ console.assert(!/^function *\( *[^ )]/.test(Function.prototype.toString.call(DateJan2042)), 'Bound function should have no formal arguments');
Поскольку правильно связанная функция не является реальным Function
объектом, невозможно получить все правильно, используя полифилл (в частности, числа 2/3,и 4/10), но вы можете попытаться реализовать как можно больше.
Реализация, о которой идет речь, пытается решить номер 6 и номер 7, подключившись к цепочке прототипов, но этого недостаточно.
Вот альтернативная реализация, которая работает немного лучше, но все еще не совершенна: http://jsfiddle.net/YR6MJ/