Function_Call Explanation
TheGreatAbyss opened this issue · 0 comments
TheGreatAbyss commented
I've always felt that the author of this course invested a lot of time in the excellent exercises themselves, but not enough effort into the explanations. Below is an explanation of the function_call problem that I wrote out for myself, and hopefully can help some others too.
(Note I did this all in a Jupyter notebook [using ijs] which I find a great learning tool )
(Double note that BERNIE is the name of the dog in my avatar)
"use strict";
function myFunction(passed1) {
console.log('called my function')
console.log(passed1)
};
// Inside myFunction.call, the value of this is myFunction itself
myFunction.call() // => called my function
// The function test below only works if the this of the function is set. In order to use it you need to use call
// or apply to set the this to the object to run on
test_obj = {a:10, b:15}
function test() {
return this.a +this.b
}
test.call(test_obj) // => 25
// These are equivalent and nothing is returned because Function.prototype isn't a function that does anything
Function.prototype.call() // => undefined
Function.prototype.call(myFunction) // => undefined
// Call is a function that applies the original function to an object or function passed in as the this,
// And then passes in the variables afterwards.
// What this is saying is that as stated above the first call would call Function.prototype
// (which doesn't do anything)
// The second call is taking the first call function and then calling it.
// The first argument to the second call function sets the the this of the first call function.
// So now the first call function is equivalent to: myFunction.call(this, arg1, arg2 etc..)
// But in order to use the first call function we still have to pass it a this, and then the arguments
// So the first argument (myFunction) is the this argument of the 2nd call function
// that sets the "this environment" of the 1st call function
// The second argument (this), is passed to the 1st call function as it's first argument (the thisArg of the 1st call)
// The 3rd argument is passed as the 2nd argument to the 1st call function which is the first argument that gets
// passed to the function
Function.prototype.call.call(myFunction, this, "BERNIE")
// => called my function
// => BERNIE
// Similar to the above but using bind instead.
// bind also takes the same arguments as call (thisArg, arg1, arg2 etc), but returns a partial function instead of
// executing it
// The this arg of bind sets the "this Environment" of call,
// What is returned is a partial implementation of call that is still expecting
// it's normal arguments: (thisArg, arg1, arg2, ...)
// But its "this environment" is now set to myFunction
testfunc = Function.prototype.call.bind(myFunction)
testfunc(this, "BERNIE")
// => called my function
// => BERNIE
// Could also be written like this
testfunc = Function.prototype.call.bind(myFunction, this)
testfunc("BERNIE")
// => called my function
// => BERNIE
// So this is the same as the above but using the slice method on Array.prototype
// So the call method is now a partial method that is still expecting (thisArg, arg1, arg2..)
// But it's thisenvironment has been set to the Array.prototype.slice method
// So you can therefore pass it any array.
slice = Function.prototype.call.bind(Array.prototype.slice)
slice([1,2,3,4],1,3) // => [2,3]
// The same as below where call sets the thisenvironment of the slice function to the array [1,2,3,4]
Array.prototype.slice.call([1,2,3,4],1,3 )
// => [ 2, 3 ]
// This doesn't work because slice is not bound to any actuall array
Array.prototype.slice([1,2,3,4,5], 1,3)
// => []