A collection of code snippets explaining:
this
bind
- arrow functions
A collection of code snippets explaining:
this
bind
var name = 'globalName'; | |
const obj = { | |
name: 'myName', | |
sayName: function () { console.log(this.name);} | |
} | |
obj.sayName(); | |
// output: myName | |
const say = obj.sayName; | |
// we are merely storing the function | |
// the value of `this` isn't magically transferred | |
say(); | |
// output: globalName | |
// now because this function is executed in global scope | |
// `this` will refer to the global var | |
const boundSay = obj.sayName.bind(obj); | |
// now the value of this is bound to the obj object | |
boundSay(); | |
// output: myName | |
// Now this will refer to the name in the obj object: 'myName' | |
const obj2 = { | |
name: "hisName" | |
}; | |
const boundSay2 = obj.sayName.bind(obj2); | |
// obj2 has no function to say its name | |
// and we want to share the same function from obj | |
boundSay2(); | |
// output: hisName | |
// what happened? | |
// `.bind` is creating a new function, with the given context | |
console.log(boundSay == obj.sayName) | |
// output: false | |
// reading | |
// 1. https://stackoverflow.com/questions/2236747/use-of-the-javascript-bind-method | |
// 2. https://gist.github.com/zcaceres/2a4ac91f9f42ec0ef9cd0d18e4e71262 |
this.age = 3; | |
const sayAge = () => { | |
console.log(this.age) | |
} | |
sayAge() | |
// output: 3 | |
// An arrow function `() => {}` does not have its own `this` | |
// (and `arguments`, `super` or `new.target`). | |
// so calling add() is looking up `this.age` in upper scope | |
function Person() { | |
this.age = 30; | |
sayAge(); | |
} | |
const p = new Person(); | |
// output: 3 | |
// instead of 30 | |
// It proves that the arrow function is looking up `this.age` in a consistent manner, | |
// by always pointing to the context when it first *created*. | |
// how to fix | |
function Person2() { | |
this.age = 30; | |
const sayAge2 = () => { | |
console.log(this.age); | |
} | |
// define the arrow function in the context that we need it | |
sayAge2(); | |
} | |
const p2 = new Person2(); | |
// output: 30 | |
// Following is a popular usage to create arrow function in class | |
// A1 | |
class A1 { | |
constructor() { | |
this.counter = 0; | |
} | |
handleClick1 = () => { | |
this.counter++; | |
} | |
handleClick2() { | |
this.counter++; | |
} | |
} | |
// class A1 will be transpiled into | |
// class A2 by Babel | |
class A2 { | |
constructor() { | |
this.handleClick1 = () => { | |
this.counter++; | |
}; | |
this.counter = 0; | |
} | |
handleClick2() { | |
this.counter++; | |
} | |
} | |
// The original intention is to declare an instance method by an arrow function | |
// `handleClick1`, however, the arrow function is moved into constructor after tranpiling | |
// as an instance member. | |
// | |
// The arrow function `handleClick1` is not in the prototype, with two shortcomings: | |
// 1. performance could be problematic since all instances create their own members. | |
// 2. can not be called by `super` since they are inside constructors. | |
// > You should only bind with .bind() or arrow function a method if you’re going to pass it around. | |
// reading | |
// 1. https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1 |