[JS] this
2022. 8. 6. 22:03ㆍ학습/JavaScript
반응형
this
this는 실행 컨텍스트가 생성될 때 결정이 됩니다. 그 뜻은 함수를 호출할 때 결정된다고 할 수 있습니다.
this를 구분하는 방법은 대표적으로 함수와 메서드 입니다.
전역공간의 this
- 전역공간의 this는 전역 객체를 가리킵니다.
- 브라우저 환경: window
- Node.js 환경: global
전역 변수
전역 변수를 선언하면 JS엔진은 이를 전역객체의 프로퍼티로 할당합니다.
좀더 개념을 확장하면 JS의 모든 변수는 특정객체(LexicalEnvironment)의 프로퍼티로 동작함
그렇다면 var로 선언한 전역변수와 전역객체의 프로퍼티의 차이는 무엇일까요?
- 호이스팅
- configutration 의 True, False
window.a = 1;
var b =2;
delete window.a;
delete b;
console.log(a); //Uncaught ReferenceError: a is not defined
console.log(b); //2
// 'b'는 configuration이 'false'
// 의도치 않게 삭제되는 것을 방지함
함수와 메서드
- 함수는 그 자체로 독립적인 기능을 수행
- 메서드는 자신이 호출한 대상 객체에 관한 동작을 수행
- 메서드는 객체의 메서드로서 호출할 경우에만 메서드로 동작
- 그렇지 않으면 함수로 동작
함수 호출과 메서드 호출을 구분하는 법은 함수 앞의 점(.)의 유무 입니다.
obj.run();//메서드 호출
run();//함수 호출
상황에 따른 this
1. 메서드의 this
- this에는 호출한 주체에 대한 정보가 담깁니다.
- 즉, 점(.) 앞에 있는 객체를 가리킵니다.
2. 함수의 this
- 함수의 this는 전역객체를 가리킵니다.
- 메서드 내부의 함수일지라도 함수로서 호출되면 this는 전역 객체를 가리킵니다.
주변환경의 this를 받기 위해선 어떻게 할까요?
- 변수(self)를 활용해서 this 우회하기
var obj = {
outer: function () {
console.log(this); // {outer: ƒ}
var self = this;
var inner = function () {
console.log(self); // {outer: ƒ}
}
inner();
}
}
obj.outer();
3. this를 바인딩하지 않는 화살표 함수
- ES6에서 '화살표 함수'를 도입하였습니다.
- 이 함수는 this를 바인딩하지 않습니다.
- 상위 스코프의 this를 그대로 활용할 수 있습니다.
4. 콜백함수에서의 this
콜백함수는 제어권을 가진 함수에 따라 this의 대상이 다릅니다.
- 따로 지정하지 않는다면 전역객체를 가리킵니다.
addEventListener
의 경우 자신의this
를 상속하도록 정의합니다.
document.body.innerHTML += '<button id="a"></button>';
document.body.querySelector('#a')
.addEventListener('click', function (e) {
console.log("this:",this,"e:",e)
});
5. 생성자 함수 내부에서의 this
"생성자"는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다.
JS는 new 명령어와 함께 함수를 호출하면 생성자의 역할을 합니다.
- 생성자함수로 함수가 호출된 경우의 this는 인스턴스 자신이 됩니다.
생성자의 prototype
프로퍼티를 참조하는 __proto__
프로퍼티를 가지는 인스턴스를 만들고, 공통 속성 및 개성을 해당 객체(this)에 부여합니다.
var Dog = function (name, age) {
this.type = '포유류';
this.name = name;
this.age = age;
};
var terry = new Dog('테리',6);
console.log(terry)
명시적으로 this 바인딩하는 방법
1. call 메서드
Function.prototype.call(thisArg[, arg1[, ...]])
- 메서드의 호출 주체인 함수를 즉시 실행하도록합니다.
- 메서드의 첫 번재 인자를
this
로 바인딩합니다. - 이후 매개변수는 호출할 함수의 매개변수로 합니다.
var func = function(a,b,c) {
console.log(this,a,b,c);
}
func(1,3,4);//Window {window: Window, self: Window, document: document, name: '', location: Location, …} 1 3 4
func.call({x:1},2,3,4);//{x: 1} 2 3 4
- 메서드의 함수는 원래 '점(.)' 앞에있는 함수를 this로 받지만 call 메서드는 지정한 객체가 this가 됩니다.
2. apply 메서드
Function.prototype.apply(thisArg[, argsArray])
- 두 번째 인자를 배열로 받아서 그 배열의 요소들을 호출할 함수의 매개변수로 지정합니다.
var func = function(a,b,c) {
console.log(this,a,b,c);
}
func(1,3,4);//Window {window: Window, self: Window, document: document, name: '', location: Location, …} 1 3 4
func.apply({x:1},[2,3,4]);//{x: 1} 2 3 4
그럼 call, apply는 언제 사용할까요?
- 유사 배열 객체에 배열 메서드 적용
var obj = { 0:'a', 1:'b', 2:'c', length:3 }; Array.prototype.push.call(obj,'d'); console.log(obj); // {0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4} var arr = Array.prototype.slice.call(obj); console.log(arr); // ['a', 'b', 'c', 'd'] //얕은 복사만 진행하는데 중첩객체는 그럼??
- 유사배열 객체에는
arguments
,NodeList
등이 있습니다. - 문자열의 경우
- length 프로퍼티가 읽기 전용이기 때문에 원본 문자열을 변경하는 메서드에는 에러가 나타납니다.
- concat 역시 제대로 된 결과를 얻지 못합니다.
var str = 'string' Array.prototype.push.call(str,'d'); //Uncaught TypeError: Cannot assign to read only property 'length' of object '[object String]'
- 그런데 ES6에서
Array.from
을 도입합니다.- 유사배열객체 또는 순회 가능한 모든 종류의 데이터를 배열로 만드는 게 가능해졌습니다.
- 유사배열 객체에는
- 생성자 내부에서 다른 생성자 호출
function Person(name,age) {
this.name = name;
this.age = age;
}
function Coach(name, age, tech) {
Person.call(this, name, age); //this는 Coach 인스턴스를 나타냄
this.tech = tech;
}
var chulsu = new Coach("철수", 34, "Vue");
console.log(chulsu);//Coach {name: '철수', age: 34, tech: 'Vue'}
apply
: 여러 인수를 묶어 하나의 배열로 전달하고 싶을 때
var numbers = [2,3,45,56];
var max = Math.max.apply(null,numbers);
console.log(max);
//번외 ES6-전개연산자
var numbers = [2,3,45,56];
var max = Math.max(...numbers);
console.log(max);
3. Bind
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]])
- call 처럼 함수를 실행하지는 않고 반환만 진행합니다.
- 함수에 this를 미리 적용
- 부분 적용함수를 구현
- bind를 호출할 때 전달했던 인수들의 뒤에 이어서 등록됨
var func = function (a, b, c, d) { console.log(this, a, b, c, d); }; var Subfunc = func.bind({ x: 1 }, 4, 5); Subfunc(6, 7); //{x: 1} 4 5 6 7
- bind 메서드가 적용된 함수는 name 프로퍼티에 'bound'가 붙습니다.
console.log(Subfunc.name); //bound func
이 글은 "코어자바스크립트" 내용에 기반하여 작성한 글입니다.
잘못된 부분이나 이해가 잘못된 부분에 대해서는 댓글로 써 주시면 감사하겠습니다!
반응형
'학습 > JavaScript' 카테고리의 다른 글
[JS] 클로저 (0) | 2022.08.07 |
---|---|
[JS] 콜백함수 (0) | 2022.08.07 |
[JS] 실행 컨텍스트 (0) | 2022.07.31 |
[JS] 원시타입과 참조타입의 차이 (0) | 2022.07.16 |
[JS]자바스크립트란? (0) | 2021.11.18 |