Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Function.prototype.bind = function(bind) {
var self = this;
return function(){
var args = Array.prototype.slice.call(arguments);
return self.apply(bind || null, args);
};
};
15.3.4.3: In Edition 3, a TypeError is thrown if the second argument passed to Function.prototype.apply is neither an array object nor an arguments object. In Edition 5, the second argument may be any kind of generic array-like object that has a valid length property.
Math.max.apply(null, {length: 2, 0: 0, 1: 1}); // 1
(function(apply) {
try {
Function.apply(null, {length: 0});
}
catch (error) {
Function.prototype.apply = function(context, object)
{
if (Object.prototype.toString.call(object) !== '[object Array]')
object = Array.prototype.slice.call(object);
return apply.call(this, context, object);
}
}
}(Function.prototype.apply));
А вот к чему здесь альтернативная реализация apply (которые, в отличие от bind, о котором говорится в топике, поддерживается уже повсюду), честно говоря, не совсем понял.
Function.prototype.bind = function(bind) {
var slice = Array.prototype.slice, self = this, args = slice.call(arguments,1);
return function(){
return self.apply(bind || null, args.concat(slice.call(arguments)));
};
};
var fn = $.proxy(object.f, object);
setTimeout(fn, 3000);var fn = function(){ object.f() };
setTimeout(fn, 3000);var fn = $.proxy(object.f, object);
window.addElementListener('load', fn, 3000);
// vs
var fn = function(){ object.f() };
window.addElementListener('load', fn, 3000);
var fn = function(){ return object.f() };
window.addElementListener('load', fn, 3000);
var fn = function(){ return object.f.apply(object, argument) };
window.addElementListener('load', fn, 3000);
var fn = object.f.bind( object );
window.addElementListener('load', fn, 3000);
add<strong>Element</strong>Listener? Java? Судя по аргументам, вроде, нет. Но тогда что́?!var object = {
x: 3,
f: function() {
console.log(this.x);
}
}
_.bindAll(object);
f всегда будет выполняться в контексте объекта object.Function.prototype.bind = function(thisArg) {
function boun() {
var arg = part.concat(Array.prototype.slice.call(arguments));
return this instanceof boun
? Function("_", "return new _(" + arg + ")")(self)
: self.apply(thisArg, arg);
}
var part = Array.prototype.slice.call(arguments, 1), self = this;
return boun;
};
/* Привязывание функций */
function bind_fun() {
function add($A, $B, $C) {
var $D = $A + $B + $C;
console.log('Аргументы: %s\nРезультат: %s\n',
Array.prototype.slice.call(arguments), $D);
return $D;
}
bind = add.bind(null, 3, 5); //
bind(7); // ==> 15 (3 + 5 + 7)
bind(17); // ==> 25 (3 + 5 + 17)
};
// https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Example:_Partial_Functions
/* частичные функции */
function _Partial_Functions() {
function Point(a, b) {this.x = a;this.y = b;}
Point.prototype.toString = function() {return this.x + "," + this.y;};
var bind = Point.bind(null, 0), boun = new bind(5);
console.log(boun.toString()); // ==> 0,5
};
// https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Example:_Creating_a_bound_function
/* Пример: частичные функции */
function _Creating_a_bound_function() {
this.x = 9;
var module = {x: 81, getX: function() { return this.x; }};
$A = module.x // ==> 81 Значение свойства 'x' module
$B = module.getX(); // ==> 81 Значение метода 'getX' module
getX = module.getX; // ссылка на функцию module.getX
$C = getX(); // ==> 9 this === глобальный объект
boundGetX = module.getX.bind(module); // bind функции this === module
console.log($A, $B, $C, boundGetX()); // ==> 81 81 9 81
}
_Creating_a_bound_function()
_Partial_Functions()
Function("_", "return new _(" + arg + ")")(self)Point.bind(null, { my: 'object' })
function Point(depend, a, b) {
this.depend = depend;
this.x = a;
this.y = b;
}
Point.prototype.toString = function() {return this.x + "," + this.y;};
var bind = Point.bind(null, [6, 5, 4]);
var boun = new bind(1, 2);
console.log(boun.toString()); // какой результат? (5,4)
Function("_", "return new _(" + arg + ")")(self)На: Function('$,_', 'return new $(' + arg.map(function (a, b) { return '_[' + b + ']'}) + ')')(self, arg)Попробуйте так.Function.prototype.bind = function(thisArg) {
function boun() {
var arg = part.concat(Array.prototype.slice.call(arguments));
return this instanceof boun
? Function('$,_', 'return new $(' + arg.map(function (a, b) { return '_[' + b + ']'}) + ')')(self, arg)
: self.apply(thisArg, arg);
}
var part = Array.prototype.slice.call(arguments, 1), self = this;
return boun;
};for (var i = 0; i < this.buttons.length; i++) {
this.buttons[i].onclick = this.clickHandler.bind(this, this.buttons[i]);
}
@TheShock 5 июня 2016 в 00:11
Скажите, зачем усложнять и делать через `eval`, если на mdn есть полифил без него?
@XGuest 14 июня 2016 в 02:56
Использовал такой вариант, писал давно, сейчас не нужен
Function.prototype.bind = function(thisArg) {
function boun() {
Array.prototype.unshift.apply(arguments, part); // unshift arguments
return self.prototype.constructor // constructor для {} и ()
.apply(thisArg || this, arguments); // в __proto__
}
Array.prototype.shift.apply(arguments); // shift arguments
var part = arguments, self = this;
boun.prototype = self.prototype; // Для {}
return boun; // Если () то лишняя команда
};Но как минимум лишние: Извините, забыл об основных конструкторах, исправил.
Function.prototype.bind = function(thisArg) {
function boun() {
Array.prototype.unshift.apply(arguments, part);
return self.apply(thisArg || this, arguments);
}
Array.prototype.shift.apply(arguments);
var part = arguments,
self = this.prototype
? this.prototype.constructor
: thisArg;
boun.prototype = self.prototype;
return boun;
};
Привязка контекста (this) к функции в javascript и частичное применение функций