khaliloos benk
khaliloos benk

Reputation: 87

using bind method with () function javascript

I have one question, when I use bind with arrow function doesn't work so if there 's anyone can explain it to me.

let username={
  email:"test@test",
  login:()=>{console.log(this.email);}
};`

when i tap username.login()return undefined also if u tap username.login.bind(username) if there's anyone who can help I will be very thankful. I m all ears for more info.

Upvotes: 0

Views: 50

Answers (2)

Robin Zigmond
Robin Zigmond

Reputation: 18249

Have a read of this from MDN to understand how arrow functions deal with this differently from other functions. This, indeed, was the main reason arrow functions were introduced - they are not primarily about a "nicer" syntax, even though this seems to be how many developers today use them. (And there is nothing wrong with using them that way, but you do absolutely have to be aware of how these functions behave differently.)

As the MDN link explains, the fact that arrow functions "inherit" the this of their enclosing scope is a convenience in many common situations. But, as you have discovered, it also causes problems in cases where you rely on the value of this to be a particular object. Here is a simple demonstration of how the difference arises in your case:

let username1={
  email:"test@test",
  login:()=>{console.log(this.email);}
};

let username2={
  email:"test@test",
  login:function(){console.log(this.email);}
};

username1.login(); // logs "undefined"
username2.login(); // works as expected

The reason is because in username2, with the "ordinary" function (not an arrow function) follows the normal rules for what this means inside a function. These are too difficult to go into here (although less difficult than are often thought, and I would well advise understanding what they are) - suffice to say though that the value of this inside a function depends on how the function was called, and that usually, when you call a function as a direct property of an object, as you do with username2.login() here, this will be that object (namely username2).

But with username1.login(), the function is an arrow function, which as the MDN article explains, does not follow these standard rules. Instead the this is adopted from the enclosing scope. Here that's the global scope, not a function scope, so there isn't actually a "real" this to use - and that results in the global (window) object being chosen instead. And since window.email doesn't exist, you get undefined. As proof that this is indeed the global object, recall that window.email is one and the same as a global variable called email. So if we amend the snippet to define a global variable of that name, its value is printed instead:

var email = "this is the global email var";

let username1={
  email:"test@test",
  login:()=>{console.log(this.email);}
};

let username2={
  email:"test@test",
  login:function(){console.log(this.email);}
};

username1.login(); // logs global email variable
username2.login(); // works as expected

So that's what's happening here. (Also note that, in real code, the enclosing scope will most often not be global. But it's still quite likely that the this value of the function concerned will be the global object, and even if it isn't, you'll still see undefined printed here unless that particular object happens to have an email property defined.)

The moral of the story is not to use arrow functions for object methods - because any reference to this inside them will not behave as you likely expect. In fact my personal reference is not to use arrow functions at all unless you either need their specific modification of the this rules, or if you need a "throwaway" one-line anonymous function (for example as a function argument to an array's map or filter), in which case the arrow function can make the code more readable. But increased readability and brevity is not the main reason arrow functions exist.

Upvotes: 1

ManUtopiK
ManUtopiK

Reputation: 4714

Arrow function is always called with the context in which it was defined. Just use a normal function.

let username={
  email:"test@test",
  login: function() {console.log(this.email);}
};`

Take a look at ECMAScript 2015 Spec:

Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.

Upvotes: 0

Related Questions