Skip to content

Instantly share code, notes, and snippets.

@m4r00p
Created February 20, 2013 23:24
Show Gist options
  • Save m4r00p/5000664 to your computer and use it in GitHub Desktop.
Save m4r00p/5000664 to your computer and use it in GitHub Desktop.
Elaborate about Function.prototype.bind and polyfills.
// Case 1:
// Bind clean way.
var obj = {
a: 'obj ',
fn: function (b) {
console.log(this.a + b);
},
attachEvents: function () {
this.attachEvent('onSomething', this.fn.bind(this, 'argB'));
}
};
// consequences:
// * ecma-262 5th edition standard
// * obj.fn can be reuse multiple times with different set of arguments and context
// * it could be use in very flexible way obj.fn.bind({a: 'swithed context'}}, 'argB');
// * can be use pretty clear with for loop
// for (var i = 10; --i;) {
// listOfDomElements[i].onclick = this.fn.bind(this, 'element' +i);
// }
// * clean, sligtly slower because overhead related with function execution (who cares if it's matter only for millions of execution)
// Case 2:
// Stored/cached context.
var obj = {
a: 'obj ',
attachEvents: function () {
var that = this;
var fn = function (b) {
console.log(that.a + b);
};
this.attachEvent('onSomething', fn);
that = {a: 'magicaly switched context'};
}
};
// consequences:
// * tricky based on fact that each function in javascript is closue (store reference to outer enviroment)
// * that value is resolve by jumpig to outer enviroment/scopes so it has very magic side effects
// (u can switch context in run time even after attaching it see example above)
// * can't be reuse outside the method attachEvents
// * can't carry additional arguments
// * theoretically faster than native bind because u don't execute additional function u just create function and that is resolve in moment of execution.
// (interpeter just need to jump one hop above to resolve value in directly outer enviroment/scope)
// Case 3:
// Try to solve carrying arguments.
var obj = {
a: 'obj ',
attachEvents: function () {
var that = this;
var b = 'argB';
var fn = function () {
console.log(that.a, + b);
};
this.attachEvent('onSomething', fn);
b = 'argB switched in run time';
}
};
// consequences:
// * it adds more curiosity because the same rules of value resolving by looking to outer sope are apply to b as well (see above)
// * to totaly unusable in predictable way in loop (also side effect of resolving it by looking in outer scope)
// for (var b = 10; --b;) {
// listOfDomElements[b].onclick = fn;
// }
// after executing onclick listeners for each it will be 0 (value for last iteration)
// * in most cases ends with not clear and predictable code if u are not aware of consequences
// Case 4:
// Glory salvation/solution.
var obj = {
a: 'obj ',
attachEvents: function () {
var that = this;
var arg = 'argB';
var fn = function (b) {
console.log(this.a + b);
};
// decorate original function with scope which cach orginal and context
fn = (function (ctx, cachedArg) {
var originalFn = fn;
return function () {
originalFn.call(ctx, cachedArg);
};
}(this, arg));
this.attachEvent('onSomething', fn);
b = 'argB switched in run time';
}
};
// consequences:
// * now it works completly the same like bind
// * looks like crap, is hard to read, understand and so on
// * self-obfuscated i would say, thing which should be avoided in any code base
// * a litle bit improved (with support for handling dynamicaly number of arguments) is polyfill for bind (see below and find similarities)
if (!Function.prototype.bind) {
Function.prototype.bind = function(ctx) {
var that = this;
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(ctx, args.concat(Array.prototype.slice.call(arguments)));
};
};
}
// Recap:
// In case of events* doesn't make any sense to use tricky and confusing way with dangerouse of unpredictable behavior
// * - if u don't need to handle millions of events at the second, but anyway then u need to improve it in other more efective way
// rid of event way comunication (rid of execution triggerEvent and manually execute function directly on object reference)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment