Call, apply, bind

by Ivan Gerasimenko

HTML

<h4>По мотивам: <a href="http://habrahabr.ru/post/199456/">Bind, Call и Apply в JavaScript</a></h4>

JavaScript

console.clear();
var log = function(msg) { console.log(msg); }

var context1 = { foo: "bar" };
function returnFoo(arg1) {
    return this.foo + " : " + arg1;
}

log(
    returnFoo.call(context1, "call-arg1")
);

log(
    returnFoo.apply(context1, ["apply-arg1"])
);

var returnFooBoundToContext1 = returnFoo.bind(context1);
// new fnc bound to context1
log( 
    returnFooBoundToContext1("bind-arg1")
);


// super binder
var callBinder = Function.prototype.call.bind(Function.prototype.bind);
var returnFooWithContext1Call = callBinder(returnFoo, context1);
log(
    returnFooWithContext1Call("callBinder-arg1")
);

// why? undefined
var applyBinder = Function.prototype.apply.bind(Function.prototype.bind);
var returnFooWithContext1Apply = applyBinder(returnFoo, context1);
log(
    returnFooWithContext1Apply(["applyBinder-arg1"])
);

// 
var callExec = Function.prototype.call.bind(Function.prototype.call);
var stringResult = callExec(returnFoo, context1, "callExec-arg1");
log( stringResult );


//// experiment with bind - change bound function
log(""); log("experiment with bind - change bound function");

var objTest = {  testVal: "hey, you!" };
function traceObj(arg1) {
    return this.testVal + arg1;
}

var boundTraceToObjTest = traceObj.bind(objTest);
log( boundTraceToObjTest(" - not change func traceObj!") );

traceObj = function(arg1) {
    return this.testVal + " : changed traceObj!!! : " + arg1;
}
log( boundTraceToObjTest(" - new arg1!") );
log( traceObj.call(objTest, " bound arg1") );


/// question
var obj = { name: 'my name' }
function nameTracer() {
    var arr = [].slice.call(arguments);
    return this.name + ' : ' + arr.join(', ');
}
var callBinder = Function.prototype.call.bind(Function.prototype.bind);
var nameTracerBoundToObj = callBinder(nameTracer, obj);
log( nameTracerBoundToObj('a1', 'a2', 'a3') );

var applyBinder = Function.prototype.apply.bind(Function.prototype.bind);
var nameTracerBoundToObjApply = applyBinder(nameTracer, obj);
log(...