[JS] this(코어자바스크립트)

mokyoungg·2020년 12월 20일
0

코어자바스크립트

목록 보기
3/3
post-custom-banner

모든 내용의 출처는 코어 자바스크립트와 PoiemaWeb입니다.

http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&linkClass=&barcode=9791158391720

https://poiemaweb.com/es6-block-scope


  • 함수와 객체(메서드)의 구분이 느슨한 자바스크립트에서 this는 실질적으로 이 둘을 구분하는 거의 유일한 기능이다.

1. 상황에 따라 달라지는 this

  • 자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다.
  • this는 함수를 호출할 때 결정된다.(함수 호출의 방식에 따라 결정)

1-1. 전역 공간에서의 this

  • 전역 공간에서 this는 전역 객체를 가리킨다.
  • 브라우저 환경에서 전역객체는 window이고 Node.js에선 global이다.

구글크롬(브라우저)에서 실행

console.log(this) // 
Window {window: Window, self: Window, document: document, name: "", location: Location, …}

전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로도 할당한다.

전역변수와 전역객체

var a = 1;
console.log(a) // 1
console.log(window.1) //1

그러나 let으로 선언하면 전역객체의 프로퍼티로 할당하지 않는다.

전역변수와 전역객체(2)

let b = 1;
console.log(b) //1
console.log(window.1) // undefined

전역객체는 모든 객체의 유일한 최상위 객체를 의미한다.
var 키워드로 선언된 변수는 전역 변수로 사용하면 전역 객체의 프로퍼티가 된다.
let 키워드로 선언된 변수는 전역 변수로 사용하는 경우, let 전역변수는 전역객체의 프로퍼티가 아니다.
let 전역변수는 보이지 않는 개념적인 블록내에 존재하게된다.

출처 : https://poiemaweb.com/es6-block-scope

1-2.메서드로서 호출할 때 그 메서드 내부에서의 this

함수 vs 메서드

  • 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치이다.
  • 이 둘을 구분하는 유일한 차이는 독립성이다.
  • 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.
  • 함수 앞에 점(.)의 여부만으로 구분할 수 있다.(대괄호 표기법도 가능)

함수로서의 호출, 메서드로서 호출

var func = function (x) {
  console.log(this, x);
}
func(1); // Window{...} 1
var obj = {
  method: func
};
obj.method(2); // { method: f } 2

메서드 내부에서의 this

  • this에는 호출한 주제에 대한 정보가 담긴다.
  • 메서드로 호출한 경우, 호출 주체는 함수명(프로퍼티명) 앞의 객체이다.

메서드 내부에서의 this

var obj = {
  methodA: function() { console.log(this },
  inner: {
    methodB: function() { console.log(this) }
  }
}
obj.methodA // { methodA: f, inner: { ... } } ( === obj)
obj.inner.methodB // { methodB: f } ( === obj.inner )

1-3. 함수로서 호출할 때 그 함수 내부에서의 this

  • 실행컨텍스트를 활성화할 당시에 this가 지정되지 않은 경우, this는 전역객체를 가리킨다.
  • 함수에서의 this는 전역객체를 가리킨다.

메서드의 내부 함수에서의 this를 우회하는 방법

  • 호출 당시 주변 환경의 this를 그대로 상속받아 사용할 수 있는 방법
  • ES5까지는 자체적으로 내부함수에 this를 상속할 방법은 없다.
  • 변수를 활용해야 한다.

내부함수에서의 this를 우회하는 방법

var obj = {
  outher: function() {
    console.log(this);				// { outer: f }
    var innerFunc1 = function() {
      console.log(this);			// Window{ ... }
    }
    innerFunc1();
    //여기서 this를 변수에 할당
    var self = this;
    var innerFunc2 = function() {
      console.log(self);			// { outer: f }
    };
    innerFUnc2();
  }
};
obj.outer()

this를 바인딩하지 않는 함수

  • ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제를 보완
  • this를 바인딩하지 않는 화살표 함수를 도입
  • 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어 상위 스코프의 this를 활용

this를 바인딩하지 않는 화살표 함수

var obj = {
  outer: function(){
    console.log(this);			// { outer: f }
    var innerFunc = () => {
      console.log(this);		// { outer: f }
     }
    innerFunc();
  }
};
obj.outer()

여기서 this가 바인딩하는 것은 전역객체이기 때문에 이를 방지하는 방법을 말하고 있다.

1-4. 콜백함수 호출 시 그 내부함수의 this

  • 함수A가 함수B의 콜백함수일 때 함수 A는 함수B의 내부 로직에 따라 실행된다.
  • this 역시 함수 B 내부 로직에서 정한 규칙에 따라 값이 결정된다.
  • 특별히 정의하지 않은 경우에는 기본적으로 젼역객체를 바라봄

1-5. 생성자 함수 내부에서의 this

  • 자바스크립트는 함수에 생성자로서의 역할을 부여
  • new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작.
  • 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 된다.

생성자 함수

var Cat = function(name, age) {
  this.bark = '야옹',
  this.name = name,
  this.age = age;
};
var nabi = new Cat('나비', 7);
cosole.log(nabi) // Cat { bark: '야옹', name: '나비', age: 7 }

2. 명시적으로 this를 바인딩하는 방법

this에 별도의 대상을 바인딩하는 방법

2-1. call 메서드

Function.prototype.call(thisArg[,arg1[,arg2[, ...]]])

  • call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
  • 첫 번째 인자를 this로 바인딩
  • 이후의 인자들을 호출할 함수의 매개변수로 활용

call 메서드

var func = function(a, b, c) {
  console.log(this, a, b, c);
}
func(1, 2, 3)	// Window{ ... } 1 2 3
func.call({ x: 1 }, 4, 5, 6) // { x: 1 } 4 5 6

2-2. apply 메서드

Function.prototype.apply(thisArg[, argsArray])

  • apply 메서드는 두 번째 인자를 배열로 받음
  • 그 배열의 요소들을 호출할 함수의 매개변수로 지정

apply 메서드

var func = function(a, b, c) {
  console.log(this, a, b, c);
};
func.apply({ x: 1 }, [4, 5, 6]); 	// { x:1 } 4 5 6
var obj = {
  a: 1,
  method: function(x,y) {
    console.log(this.a, x, y);
  }
}
obj.method.apply({ a:4 }, [5, 6] 	// 4 5 6

call/apply 메서드는 명시적으로 별도의 this를 바인딩하면서
함수 또는 메서드를 실행하는 훌륭한 방법이지만
오히려 이로 인해 this를 예측하기 어렵게 만들어 코드 해석을 방해한다는 단점이 있다.

2-3. bind 메서드

Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])

  • 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드
  • bind메서드는 함수에 this를 미리 적용하는 것과 부분 적용 함수를 구현하는 두 가지 목적을 지닌다.

bind 메서드

var func = function(a, b, c, d) {
  console.log(this, a, b, c, d)
}
func(1, 2, 3, 4); 		// WIndow{ ... } 1 2 3 4
var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8); 	// { x:1 } 5 6 7 8
var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7)			// { x: 1 } 4 5 6 7
bindFUnc2(8, 9)			// { x: 1 } 4 5 8 9

name 프로퍼티

  • name 프로퍼티에 bind의 수동태인 'bound' 접두사가 붙는다.
  • bound 함수명1 = 함수명1(원본함수)에 bind 메서드를 적용한 함수

name 프로퍼티

var func = function(a, b, c) {
  console.log(this, a, b, c);
}
var bindFunc = func.bind({ x:1 }, 4, 5)
console.log(func.name);		// func
console.log(bindFunc.name);	// bound func

2-4. 화살표 함수의 예외사항

  • 화살표 함수는 실행 컨텍스트 생성 시 this를 바인딩하는 과정이 제외
  • 즉 함수 내부에는 this가 없음
  • 접근하고자 하면 스코프체인상 가장 가까운 this에 접근
var obj = {
    outer: function(){
        console.log(this);		// { outer: f }
        var innerFunc = () => {
            console.log(this);		// { outer: f }
        };
        innerFunc();
    }
}

profile
생경하다.
post-custom-banner

0개의 댓글