As an exercise, I am trying to create my own bind() function using apply() and prototypal inheritance that I have just learned.
This is my code:
// Create your own bind() using call() and apply()
const lizard = {
phrase: 'slither',
say(phraseToSay) {
if (!phraseToSay) phraseToSay = this.phrase
console.log('sss' + phraseToSay)
},
}
const dragon = {
phrase: 'sizzle',
}
// My Answer
Function.prototype.mybind = function (object) {
return () => this.apply(object, arguments)
}
// Solution
Function.prototype.solbind = function (object) {
let self = this
return function () {
self.apply(object, arguments)
}
}
dragon.say = lizard.say.mybind(dragon)
lizard.say()
dragon.say()
lizard.say('sexy')
dragon.say('sexy')
This is the Output:
ssslither
sss[object Object]
ssssexy
sss[object Object]
The solution is to use self=this
. But it looks ugly in my eyes...
I am trying to do it with just this and arrow functions. But for some reason, apply()
is passing the first argument which is the object itself as an actual argument of the target function. I do not understand why this is and how I can achieve the result I want without saving this
into another variable.
When you do:
.... = function (object) {
return () => this.apply(object, arguments)
}
You're referring to the arguments
object bounded to the outer function expression, not your arrow function, as arrow functions don't have their own arguments binding. In this case, that arguments object will contain dragon
, as you're using:
dragon.say = lizard.say.mybind(dragon)
So, your arguments object will contain dragon
which will be passed as an argument to your say
method when using .apply(object, arguments)
.
In the case of the provided solution, they're returning a function expression, which, unlike an arrow function, does have its own arguments
binding, so in that case, the arguments
object refers to the arguments passed into the function returned by solbind()
.
You can fix your code by using ES6 rest parameter syntax (...)
instead of referring to the arguments object. This way args
will refer to the arguments passed into the "bound" function:
// Create your own bind() using call() and apply()
const lizard = {
phrase: 'slither',
say(phraseToSay) {
if (!phraseToSay) phraseToSay = this.phrase
console.log('sss' + phraseToSay)
},
}
const dragon = {
phrase: 'sizzle',
}
// My Answer
Function.prototype.mybind = function (object) {
return (...args) => this.apply(object, args)
}
// Solution
Function.prototype.solbind = function (object) {
let self = this
return function () {
self.apply(object, arguments)
}
}
dragon.say = lizard.say.mybind(dragon)
lizard.say()
dragon.say()
lizard.say('sexy')
dragon.say('sexy')