Skip to content

Instantly share code, notes, and snippets.

@kimyongin
Created December 30, 2018 12:09
Show Gist options
  • Save kimyongin/26b54f4d8fbecd4aae88dd77a7ed8496 to your computer and use it in GitHub Desktop.
Save kimyongin/26b54f4d8fbecd4aae88dd77a7ed8496 to your computer and use it in GitHub Desktop.
'use strict'
// This & Binding (Implicit, Explicit, Hard, New) & Arrow Function (Lexical Scope)
// -------------------------------------------------------------------------------
// [1.기본 바인딩] hello(thing) 은 hello.call(this, thing) 의 syntactic sugar 이다.
console.log("[1]")
function hello(thing) {
console.log(this + " hello " + thing);
}
hello("hola"); // undefined hello hola; (this가 암시적 바인딩 되었다. non-strict-mode 에서는 window 가 바인딩 된다.)
hello.call("kim", "hola") // kim hello hola; (this가 명시적 바인딩 되었다.)
// -------------------------------------------------------------------------------
// [2.객체 바인딩] 함수 호출시점에 함수 레퍼런스(hello)에 대한 콘텍스트 객체(person)가 존재하면,
// 암시적 바인딩 규칙에 의해, 해당 콘텍스트 객체가 this 에 바인딩 된다.
console.log("[2]")
var person = {
name: "park",
hello: function (thing) {
if (!this) {
console.log("this is undefiend");
} else {
console.log(this.name + " hello " + thing);
}
}
}
person.hello("hola") // park hello hola (this가 person 으로 암시적 바인딩 되었다.)
person.hello.call({ name: "choi" }, "hola") // choi hello hola (this가 명시적 바인딩 되었다.)
// -------------------------------------------------------------------------------
// 아래 처럼 객체를 통하지 않고, 함수 레퍼런스를 직접 호출하면
// 콘텍스트 객체 암시적 바인딩[2] 이 아니라, 일반 암시적 바인딩[1] 방식으로 호출 된다.
console.log("[3]")
function func(fn, thing) {
fn(thing);
}
func(person.hello, "hola"); // this is undefiend
var personHello = person.hello; personHello("hola"); // this is undefiend
// -------------------------------------------------------------------------------
// 위와 같이 컨텍스트 객체를 잃어버리는 문제는 하드 바인딩으로 해결할 수 있다.
// 이는 ES5 Function.prototype.bind로 내장 되어 있다.
console.log("[4]")
function hardBind(fn, obj) {
return function (args) {
// 어떤식으로 호출하든, 항상 obj가 this에 하드 바인딩 된다
fn.call(obj, args);
}
}
func(hardBind(person.hello, person), "hola"); // park hello hola
var personHello = hardBind(person.hello, person); personHello("hola") // park hello hola
func(person.hello.bind(person), "hola"); // park hello hola (내장 함수 사용)
var personHello = person.hello.bind(person); personHello("hola") // park hello hola (내장 함수 사용)
// -------------------------------------------------------------------------------
// new 연산자를 통해서 객체를 생성하는 경우 new 바인딩 이 동작한다.
// new 바인딩은 this 에 새로운 객체를 바인딩 시킨다.
console.log("[5]")
function Person(name) {
this.name = name;
this.hello = function (thing) {
if (!this) {
console.log("this is undefiend");
} else {
console.log(this.name + " hello " + thing);
}
}
}
var kim = new Person("kim");
kim.hello("hola"); // kim hello hola
// 여기서도 마찬가지로, 객체를 통하지 않고, 함수 레퍼런스를 직접 호출하면 일반 암시적 바인딩으로 호출된다.
var kimHello = kim.hello; kimHello("hola"); // this is undefined
// -------------------------------------------------------------------------------
// new 호출은 아래 처럼 호출 된다고 추측해 볼수 있다.
// 사실은 new를 통해 생성된 객체는 프로토타입 연결이라는 상속과 관련된 메카니즘이 추가되어 있다.
console.log("[6]")
var park = Object.create({});
Person.bind(park)("park");
park.hello("hola");
// -------------------------------------------------------------------------------
// 지금까지 Implicit, Explicit, Hard, New 4가지 바인딩을 살펴봤는데,
// 반면 Arrow Function 은 바인딩이 아니라, 렉시컬 스코프로 this 를 접근한다.
console.log("[7]")
function Person(name) {
var that = this;
this.name = name;
this.hello = function (thing) {
console.log(that.name + " hello " + thing);
}
this.hello2 = (thing) => {
console.log(this.name + " hello " + thing);
}
}
var choi = new Person("choi");
choi.hello("hola"); // choi hello hola
var choiHello = choi.hello; choiHello("hola"); // choi hello hola
choi.hello2("hola"); // choi hello hola
var choiHello2 = choi.hello2; choiHello2("hola"); // choi hello hola
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment