// 함수를 통해 객체의 인스턴스를 생성하던 것 대신에 클래스가 등장함. // 멤버: 변수와 메소드 // 클래스 멤버: new 생성자 함수를 통해 생성된 인스턴스마다 동일한 값을 가짐.(공유함) // 클래스의 인스턴스가 생기기 전에도 클래스이름.멤버로 사용 가능. // static으로 생성된 메소드 및 prototype이 이에 해당. // 인스턴스 멤버: new 생성자 함수를 통해 생성된 인스턴스마다 다른 값을 가짐.(공유하지 않음) // 클래스의 인스턴스가 생기기 전에는 사용 불가능, 인스턴스이름.멤버로 사용 가능 // 생성자 함수 내부에 작성된 애들이나 static 키워드를 쓰지 않고 생성한 메소드들이 해당됨.
classC { constructor() { // 생성자 함수 외부에서 인스턴스 변수를 선언하지 못한다. this.a = 1; this.b = () => {};
// 인스턴스 멤버(변수, 메소드)를 포함하고 있는 객체 // { // a: 1, // b: () => {}, // __proto__: { // 상속받는 놈이기 때문에 바로 this.d()와 같이 사용 가능. // 위에 있는 놈들과 이름이 같다면 위에 있는 놈들이 우선 순위를 가짐. // d: function() {}, // e: function() {}, // f: function() {}, // g: function() {} // } // } console.log(this); }
// 클래스 메소드의 this는 // 클래스 멤버(변수, 메소드) 등등을 담고있는 생성자 함수이다. // 클래스 변수는 클래스 내에서 선언하지 못하고, // className.prototype.variable = value 와 같이 선언한다. statica() { // function, 함수 또한 객체기 때문에 프로퍼티로 접근이 가능하다. console.log(typeofthis); // new this(); 이렇게 생성자를 호출할 수도 있다.
// __proto__는 상속받는 놈들이기 때문에 바로 this.머시기로 사용할 수 있었으나 // prototype은 상속해주는 놈들이기 때문에 this.prototype.머시기로 사용해야한다. // { // a: function() {}, // b: function() {}, // c: function() {}, // prototype: { // a: 1 // } // } console.dir(this); }
staticc() { consta = () => { // 애로우 펑션은 this를 상속받음. // function, 함수 또한 객체기 때문에 프로퍼티로 접근이 가능하다. console.log(typeofthis); // new this(); 이렇게 생성자를 호출할 수도 있다.
// __proto__는 상속받는 놈들이기 때문에 바로 this.머시기로 사용할 수 있었으나 // prototype은 상속해주는 놈들이기 때문에 this.prototype.머시기로 사용해야한다. // { // a: function() {}, // b: function() {}, // c: function() {}, // prototype: { // a: 1 // } // } console.dir(this); }; a(); }
// 인스턴스 메소드의 this는 생성자 내의 this와 일치한다. d() { // 인스턴스 멤버(변수, 메소드)를 포함하고 있는 객체 // { // a: 1, // b: () => {}, // __proto__: { // 상속받는 놈이기 때문에 바로 this.d()와 같이 사용 가능. // 위에 있는 놈들과 이름이 같다면 위에 있는 놈들이 우선 순위를 가짐. // d: function() {}, // e: function() {}, // f: function() {}, // g: function() {} // } // } console.dir(this); }
e() { const a = function() { // 역시 ES5식 함수는 this를 덮어버린다. // strict mode에서는 undefined // non-strict mode에서는 Window console.log(this); }; a(); }
f() { consta = () => { // 역시 애로우 펑션은 this를 상속 받음. // 인스턴스 멤버(변수, 메소드)를 포함하고 있는 객체 // { // a: 1, // b: () => {}, // __proto__: { // 상속받는 놈이기 때문에 바로 this.d()와 같이 사용 가능. // 위에 있는 놈들과 이름이 같다면 위에 있는 놈들이 우선 순위를 가짐. // d: function() {}, // e: function() {}, // f: function() {}, // g: function() {} // } // } console.log(this); }; a(); }
g() { // 인스턴스의 this에 클래스 멤버는 없다. // 따라서 클래스 멤버를 사용할 수는 없다. // this.a(); // 클래스 메소드 사용 불가. this.f(); // 인스턴스 멤버(메소드, 변수)는 사용 가능하다. } }
// 클래스 변수는 클래스 내에서 선언하지 못함. // 레거시 환경을 지원하기 위해 // 프로토타입 방식의 상속을 포기하지 못했기 때문인 걸까?? C.prototype.q = 1;
// [1].forEach()의 this인 {a: '11'}에 가려진다. // 그 이유는 forEach와 같은 함수는 자동으로 this를 바인딩하려는 성질이 있다. [0].forEach(d.a, {a: '11'}); // {a: '11'}
// 콜백 함수 내부에서 써야 외부의 this로부터 영향을 받지 않는다. [0].forEach(function() { d.e(); // d }, {a: '11'}); [0].forEach(() => d.e(), {a: '11'}); // d
[0].forEach(function() { // function() {}인데 this를 재바인딩하지 않고 {a: '11'}을 상속 받았다. // 이는 this를 바인딩 시키는 메소드로 this를 강제 바인딩 시킨 것으로 보인다. console.log(this); // {a: '11'} }, {a: '11'});
const e = { a() { console.log(this); }, b() { // setTimeout은 별개의 컨텍스트를 만든다. // 바로 실행시점에 컨텍스트를 만드는데, // 실행 시점의 this는 전역의 this(Window)가 된다. setTimeout(this.a, 1000); }, c() { setTimeout(function() { // setTimeout은 별개의 컨텍스트를 만든다. // 바로 실행시점에 컨텍스트를 만드는데, // 실행 시점의 this는 전역의 this(Window)가 된다. console.log(this); }, 2000); }, d() { setTimeout(() => { // setTimeout은 별개의 컨텍스트를 만든다. // 바로 실행시점에 컨텍스트를 만드는데, // 실행 시점의 this는 전역의 this(Window)가 된다. // 하지만 애로우 펑션을 쓰면 클로저가 형성된다. // 실행 시점의 this(Window)와 선언 시점의 this(e 객체)가 달라서 // 그것을 동기화(?)시키기 위해서 클로저가 형성되는 게 아닐까...싶다. console.log(this); // e }, 3000); } };
함수 선언 시점의 this는 e object이다.
하지만 함수 실행 시점의 this는 window가 된다. 바로 setTimeout이 별도의 컨텍스트를 만들기 때문이다.