[코어자바스크립트] - 3장. this

sypaik-dev·2023년 4월 28일
0
post-thumbnail

this 키워드

대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정됩니다.
객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적 단위로 묶은 복합적인 자료구조이다.
동작을 나타내는 메서드는 자신이 속한 객체의 상태, 즉 프로퍼티를 참조하고 변경할 수 있어야 한다. 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.

일반 함수 호출

기본적으로 this에는 전역 객체가 바인딩된다.

function order() {
	console.log(this);
  	function count() {
    	console.log(this);
    }
  	count();
}
order();

전역함수와 중첩 함수를 일반 함수로 호출하면 함수 내부의 this에는 전역 객체인 window가 바인딩된다. this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이므로 객체를 생성하지 않은 일반함수에서는 this는 아무런 의미를 가지지 않는다.

use strict

use strict 는 더 엄격한 문법 및 에러 처리를 적용하여 코드의 안전성을 높인다.

function order() {
  	'use strict';
  
	console.log(this); // undefined
  	function count() {
    	console.log(this); // undefined
    }
  	count();
}
order();

함수 내부의 this값은 전역 객체(window 객체 또는 global 객체)가 아닌 undefined가 된다. 이는 this를 의도치 않게 전역 객체에 바인딩되는 것을 방지하기 위함이다.

use strict 는 스크립트 최상단에 있어야 한다! 그렇지 않으면 엄격 모드가 활성화되지 않을 수도 있다.

콜백함수

  • setTimeout 함수
setTimeout(function() {
	console.log(this); // window;
}) // 콜백 함수가 일반 함수로 호출되었으므로 전역 객체가 바인딩된다.
const obj = {
	value: 100,
  	getName() {
    	console.log(this); // {value: 100, getName: f}
    }
  	setTimeout(function () {
    	console.log(this); // window
      	console.log(this.value) // 1
    }, 100)
}
const obj = {
	value: 100,
  	getName() {
    	const that = this;
    setTimeout(function () {
    	console.log(that.value); // 100
    }, 100)
    }
};

obj.getName()
  • forEach
[10, 20, 30].forEach((num) => {
	console.log(this, num); // widnow, num;
})
  • addEventListener
document.body.querySelector('.btn').addEventListener('click', function(e) {
	console.log(this, e) // 
})

메서드 호출 (암시적 바인딩)

함수가 객체의 프로퍼티 값이면 메서드로서 호출된다. 메서드 내부의 this는 해당 메서드를 소유한 객체, 즉 해당 메서드를 호출한 객체에 바인딩된다.

this에 바인딩될 객체는 호출 시점에 결정된다.

const aurora = {
	name: "Charlie",
  	getName() {
    	return this.name;
    }
};

console.log(aurora.getName()); // Charlie
const bell = {
	name: "Dayeon";
}

bell.getName = aurora.getName; // getName 메서드를 bell 객체의 메서드로 할당
console.log(bell.getName()); // Dayeon

const getName = aurora.getName; // getName 메서드를 변수에 할당
console.log(getName()) // '' ==> window.name과 같음!
const obj = {
	outer: function() {
    	console.log(this);
      	const inner = function() {
        	console.log(this); // 함수의 실행으로 window
        };
      	inner();
    }
};
obj.outer();

apply/call/bind 메서드에 의한 간접 호출 (명시적 바인딩)

암시적으로 바인딩되는 this는 바인딩을 쉽게 예측할 수 없는 상황이 있었다. 이러한 문제를 해결하기 위해 명시적으로 this를 고정하는 방법을 알아보자.

call 메서드

메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.

function func() {
	console.log(this.a);
}
const obj = {a: 2};
func.call(obj); // 2
func(obj); // undefined

함수의 this는 전역객체지만 call을 사용하면 구체적인 객체를 this로 지정할 수 있다.

apply 메서드

call 메서드와 유사한 기능으로 호출 주체 함수를 즉시 실행하지만 call()은 함수에 전달된 매개변수를 받지만 apply()는 인수들의 배열을 받는다.

function func(a, b, c) {
	console.log(this, a, b, c);
}

const obj = {a: 2};

func.call(obj, 10, 20, 30) // {a: 2} 10 20 30
func.apply(obj, [10, 20, 30]) // {a: 2} 10 20 30

bind 메서드

apply, call과는 달리 함수를 호출하지 않고 this로 사용할 객체만 전달한다. 즉 call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출하지만 bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.

const jasmine = {
	name: 'dh',
  	func(callback) {
    	setTimeout(callback.bind(jasmine), 100);
    }
};
jasmine.func(function() {
	console.log('hi, i'm ${this.name}'); // "hi, i'm dh"
})

생성자 함수 호출

function movie(year, genre, rating) {
	this.year = year;
  	this.genre = genre;
  	this.rating = rating;
}

const homeAlone = new movie(1991, 'comedy', 7.7);
const avatar = new movie(2009, 'fantasy', 7.9);
const oneDay = new movie(2011, 'romance', 7);

console.log(homeAlone.year); // 1991
console.log(avatar.genre); // 'fantasy'
console.log(oneDay.rating); // 7

어떤 함수를 new 명령어와 함께 생성자로서 동작하게 된다. 객체지향 언어에서는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스라고 한다. 생성자 함수란 new 연산자로 함께 호출해서 인스턴스를 생성하는 함수를 일컫는다. 따라서 생성자는 인스턴스를 만들기 위한 일종의 틀이다. 그리고 생성자 함수로 호출된 경우 this는 새로 만들어진 인스턴스 자신이 된다.

function Movie(year, genre, rating) {
  // --- (1)
  console.log(this);
  
  // --- (2)
	this.year = year;
  	this.genre = genre;
  	this.rating = rating;
  	this.getAge = function() {
    	return new Date().getFullYear() - this.year + 1;
    };
  // --- (3)
}

// --- (4)
const homeAlone = new movie(1991, 'comedy', 7.7);
const avatar = new movie(2009, 'fantasy', 7.9);
const oneDay = new movie(2011, 'romance', 7);

console.log(homeAlone.year); // 1991
console.log(avatar.genre); // 'fantasy'
console.log(oneDay.rating); // 7
  1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
  2. this에 바인딩되어 있는 인스턴스를 초기화한다.
  3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
  4. 인스턴스 생성하고 Movie 생성자 함수는 암묵적으로 this를 반환한다.

화살표 함수

화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 화살표 함수는 일반적인 바인딩 규칙을 무시하고 Lexical scope로 this를 바인딩한다. 즉 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.

profile
Frontend Developer

0개의 댓글

관련 채용 정보