http://blog.brew.com.hk/what-is-this-in-javascript/

 

What is 'this' in JavaScript?

Classes in JavaScript - Explained This article is an extended adaptation from Understanding Prototypes in JavaScript. This article is very in-depth, and may require…

blog.brew.com.hk

 

this !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

This Has Idiot Suck.

 

js에서 this란 '현재 실행하는 범위( context, scope, value,  whatever you want to call, cuz of that fxckin tricky )' 라고 아주 간단하게 설명할 수 있다. 

만일 this가 함수나 클래스 밖에 있다면 개념적으로 this는 global 실행 범위이다.  웹 브라우저에서 실행하면 window이다.

node.js에 있다면 export 객체 즉 비어있는 객체이다.

 

만약 함수안에 있다면 this의 값은 함수가 어떻게 호출되는지 거기에 달려있다.

const bar = function () { console.log(this) };
const poo = function () { 'use strict'; console.log(this); };
const foo = {};
foo.bar = bar;

bar(); // window
poo(); // undefined
foo.bar(); // bar

함수가( bar() )가 글로벌 스코프( window )에서 호출된다면 this는 window이다. 함수 블록은 영향을 못 미친다. 

엄격하게 검사한다면 ( 'use strict' ) this는 undefined로 로그 찍힌다. 뭐 이따구인지 모르겠다.

 

생성자함수( Function Constructor )에서 함수 안에 this는 생성된 객체( 모든 함수는 객체이다. in js )를 가리킨다.

// es5, es6로 작성된 아래 코드는 같은 결과다. 문법설탕됨

// ES5 ( ECAMAScript2009 )
function Car(make) {
  this.make = make;
}

// ES6 ( ECAMAScript2015 )
class Car {
  constructor(make) {
    this.make = make;
  }
}

const myCar = new Car("BMW");
myCar.make; // "BMW"

생성자 함수 안에 있는 this는 Car() 이 함수를 가리킨다. ( ?? )

 

근데 JS가 Prototype기반 언어라는걸 알고있는가 ?

JS에는 prototype link와 prototype object가 있는데 이걸 통칭해서 prototype이라 부른다.

( 나중에 prototype에 대한 내용은 #17 Prototype Inheritance and Prototype Chain [33 Concepts Every JavaScript Developer Should Know ]에서 포스팅 할거다 )

JS에 클래스 문법은 있지만 개념은 없다 ( ES6/7 기준 ). 그래서 다른 언어처럼 상속을 하고 싶을 때 JS는 함수와 new를 통해 상속을 흉내낸다.

- prototype와 this의 콜라보 예제

// 대충 공유 할 함수 하나 만든다.
// 이 생성자 함수 사람안에 this는 window가 아니라 사람을 가리킨다.
function 사람( someting ) {
	this.someting = someting;
}   

// 사람이 공유하게 될 눈, 코를 어딘가에 존재하는 사람함수의 prototype에 넣는다.
사람.prototype.눈 = 2;
사람.prototype.코 = 1;

// 사람이 공유하게 될 눈몇개임 함수를 만들어 prototype에 넣는다.
// 여기에 this는 눈몇개임 함수(객체)를 부르는 함수(객체)의 인스턴스를 가리킨다.
사람.prototype.눈몇개임 = function() { return this.someting + this.눈 };


// 선언한 변수 김씨, 박씨는 new를 사용하여 사람함수를 생성한다. 상속받는 것 처럼 생각하면된다.
var 김씨 = new 사람("김씨는 눈이 ");
var 박씨 = new 사람("박씨는 눈이 ");


// 결과
김씨.눈몇개임();  // '김씨는 눈이 2';

 

함수가 객체의 메소드라면 this 또한 객체를 가리킨다.

const foo = {};
foo.bar = function () { console.log(this); };
foo.bar(); // foo

빈 foo함수 객체가 있다. ( JS에서 모든 함수의 진짜 타입은 객체이다. )

foo함수(객체)에 bar메소드를 만들고 this를 리턴했다. bar에서 리턴한 this는 결국 foo를 가리킨다. ㅇㅋ? ㅇㅋ

 

Binding this.

.bind 아는가 ?

만약 this를 특정 객체에 묶고 싶다 ? this가 막 날라다닌데 고정시키고 싶다 ? 그럼 bind 메소드를 써야한다.

const foo = function () { console.log(this) };
const boundFoo = foo.bind("always me!"); // always me!를 boundFoo에 묶어버렸다.

foo(); // window
boundFoo(); // "always me!"

const a = {
  b: foo,
  boundB: boundFoo
}

a.b(); // a
a.boundB(); // "always me" <- a를 안 가리킨다.

bar = function () {};
bar.prototype.x = foo;
bar.prototype.boundX = boundFoo;

const myBar = new bar();

myBar.x(); // myBar
myBar.boundX(); // "always me" <- myBar를 안 가리킨다.

 

.bind는 ( Function.prototype.bind ) 객체에 묶인 this와 함께 new 함수를 리턴한다. 근데 원래 this가 가리켜야 하는 함수를 호출하지 못 한다. 

이 때문에 .call ( Function.prototype.call ) , .apply ( Function.prototype.apply ) 함수를 사용한다.  this를 고정시키지는 않지만 this를 특정 객체에 묶는다.

call, apply는 받는 첫 번째 인자를 함수 내부에서 사용할 this로 만들어준다. 차이점은 apply는 첫 번째 인자를 제외한 나머지를 배열로 받는다는 점이다. 이거 빼고는 차이점이 없다.

call, apply 예제확인

// a, b 객체 생성
const a = { here: 'a!!' };
const b = { here: 'b@@' };

// this.here에 따라 값이 바뀌도록 만듬
const say = function( whoyouare ) {
	console.log( ' my this belongs to ${this.here}, im ${ whoyouare }' );
}

// say함수의 this가 a를 가리킴
say.call( a, "playCall" ); // my this belongs to a!!, im playCall
say.apply( a, ["playApply"] ); // my this belongs to a!!, im playApply

// say함수의 this가 b를 가리킴
say.call( b, "playCall" ); // my this belongs to b@@, im playCall
say.apply( b, ["playApply"] ); // my this belongs to b@@, im playApply

// this가 가리킬게 없음
say("play"); // my this belongs to , im play

 

+ Recent posts