Питер Лайонс прав в обоих случаях. Вы хотели бы передать каждую функцию в качестве аргумента bindAll, а не передавать массив функций. А при использовании coffeescript жирная стрелка - это отличный способ привязать функцию к контексту, в котором она была определена.
Я хотел ответить , почему _.bind не работает для вас (потому что мне потребовалось много времени, чтобы разобраться). Ответ в том, что _.bind не изменяет передаваемую вами функцию, а создает новую функцию с предоставленными аргументами. Это было бы более соответствующим образом помечено createBoundFunction
. Таким образом, заставить _.bind работать в вашем примере будет просто:
this.render = _.bind(this.render, this)
this.foo = _.bind(this.foo, this)
Кроме того, при просмотре исходного кода я многое узнал о том, как связаны функции, поэтому я надеюсь, что вы не возражаете против отступления от привязки функций, начиная с того, что делает скрипт кофе.
var __bind = function(fn, me){ return function(){return fn.apply(me, arguments); }; }
CoffeeScript вставляет вышеуказанную функцию в каждый файл, который использует жирную стрелку (=>). Это старый способ. Он создает и возвращает новую функцию, которая вызывает вашу функцию и применяет передаваемый вами контекст и аргументы. Затем CoffeeScript генерирует конструктор и вызывает __bind для каждой определенной функции жирной стрелки. Для решения Питера Лиона сгенерированный код должен выглядеть так:
this.render = __bind(this.render, this)
this.foo = __bind(this.foo, this)
В моем текущем проекте у меня 9 представлений, в которых используется жирная стрелка, поэтому я определил __bind 9 раз, что, по-видимому, нарушает DRY, но кого это волнует, оно генерируется для меня.
ECMAScript5 запрещает новый метод в прототипе функции.
Function.prototype.bind(thisArg [, arg1[, arg2[, ...]]])
Этот метод уменьшит ваш код до следующего вида:
this.render = this.render.bind(this)
this.foo = this.foo.bind(this)
без внешней библиотеки или сгенерированного метода. Суть в том, что это поддерживается только в последних + лучших браузерах (FF4, IE9, CH10>), поэтому использование его исключительно будет невозможно в течение нескольких лет.
Подчеркивание объединяет эти два понятия:
_.bind = function(func, obj) {
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
var args = slice.call(arguments, 2);
return function() {
return func.apply(obj, args.concat(slice.call(arguments)));
};
};
Где nativeBind равен Function.prototype.bind. Подчеркните, проверяет наличие нового метода связывания ECMA5 и, если его нет, создает анонимную функцию, которая вызывает вашу функцию в выбранном вами контексте.
Если бы я знал или мог найти информацию о некоторых преимуществах, которые предоставляет Function.prototype.bind, я бы сказал, что нужно избегать жирной стрелки CS и использовать _.bind, особенно для магистральных проектов, где вы подчеркнули, что уже включены в ваши библиотеки , но я не знаю, что это дает преимущество, поэтому, вероятно, это не имеет значения, так или иначе.