0

I have below code.

var person1 = {
    fname: 'Cristiano',
    lname: 'Ronaldo',
    getName: function() {
        return this.fname + ' ' + this.lname;
    }
}

var person2 = {
    fname: 'Luka',
    lname: 'Modric',
    getName: function() {
        return this.fname + ' ' + this.lname;
    }
}


var logname = function() {
    console.log(this.getName());
}.bind(person1); // not working as expected when .bind() here !!!


var newlogname1 = logname.bind(person1);
newlogname1(); // prints 'Cristiano Ronaldo'

var newlogname2 = logname.bind(person2);

newlogname2(); // prints 'Cristiano Ronaldo'

var person1 = {
        fname: 'Cristiano',
        lname: 'Ronaldo',
        getName: function() {
            return this.fname + ' ' + this.lname;
        }
    }

    var person2 = {
        fname: 'Luka',
        lname: 'Modric',
        getName: function() {
            return this.fname + ' ' + this.lname;
        }
    }


    var logname = function() {
        console.log(this.getName());
    }.bind(person1); // not working as expected when .bind() here !!!


    var newlogname1 = logname.bind(person1);
    newlogname1(); // prints 'Cristiano Ronaldo'

    var newlogname2 = logname.bind(person2);

    newlogname2(); // prints 'Cristiano Ronaldo'

But if I change the below code snippet, it will work as I expected.

var logname = function() {
    console.log(this.getName());
};

var person1 = {
    fname: 'Cristiano',
    lname: 'Ronaldo',
    getName: function() {
        return this.fname + ' ' + this.lname;
    }
}

var person2 = {
    fname: 'Luka',
    lname: 'Modric',
    getName: function() {
        return this.fname + ' ' + this.lname;
    }
}


var logname = function() {
    console.log(this.getName());
};

var newlogname2 = logname.bind(person2);
newlogname2();

var newlogname1 = logname.bind(person1);
newlogname1();

What is this behavior ? What happens when I .bind() just in the declaration part of it. Can't I change what this supposed to mean when the function runs if I do like that.

prime
  • 14,464
  • 14
  • 99
  • 131
  • 1
    In the first example, `logname` is already bound with `person1`. *"the bind() function creates a new function (a bound function) with the same function body as the function it is being called on (the bound function's target function) with the this value bound to the first argument of bind(), **which cannot be overridden**."* – adiga May 12 '19 at 11:14

1 Answers1

1

.bind() only works if the function you're binding isn't already bound:

function f() {
  console.log(this.a)
}

const f_1 = f.bind({a: 1}) // As expected
const f_2 = f.bind({a: 2}) // -Ditto-
const f_2_3 = f_2.bind({a: 3}) // f_2 already bound, can't .bind() to other object

f_1()
f_2()
f_2_3()

/** Check if function is bound, as per @str's comment */
function isBound(fun) {
  return !('prototype' in fun)
}

console.log(
  isBound(f),
  isBound(f_1)
)

Update: Added way to check if function is already bound, as per @str's comment below

P Varga
  • 19,174
  • 12
  • 70
  • 108
  • 1
    Do we have a way to find whether a function is already bound or not ? – prime May 12 '19 at 11:14
  • 1
    @prime - Sadly, no, not without calling it, and that only works if it uses `this` and we can tell from the call what `this` it used. – T.J. Crowder May 12 '19 at 11:16
  • 1
    According to the [specification](https://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.bind), "*Function objects created using `Function.prototype.bind` [...] do not have a prototype property.*" So you might use that for a check. – str May 12 '19 at 11:18