반응형
- 상황에 따라 달라지는 this
- 전역 공간에서의 this
- 전역 객체를 가리킴
- 브라우저 환경 : window
- Node.js 환경 : global
- 자바스크립트의 모든 변수는 특정 객체의 프로퍼티로 동작
- 특정 객체
- : 실행 컨텍스트의 L.E(LexicalEnvironment)
- 자바스크립트의 모든 변수는 특정 객체의 프로퍼티로 동작
var a = 1; window.b = 2; console.log(a, window.a, this.a); //1 1 1 console.log(b, window.b, this.b); //1 1 1
- 삭제의 경우
- 전역 변수로 선언 시 해당 프로퍼티의 configurable 속성 (변경 및 삭제 가능성)을 false로 정의함
- : 처음부터 전역 객체의 프로퍼티로 할당한 경우 삭제 O(전역 변수로 선언시 삭제 X)
var a = 1; delete window.a; //false console.log(a, window.a, this.a); //1 1 1 var b = 2; delete b; //false console.log(b, window.b, this.b); //2 2 2 window.c = 3; delete window.c; //true console.log(c, window.c, this.c); //오류 window.d = 3; delete d; //true console.log(d, window.d, this.d); //오류
- 메서드로 호출 시 메서드 내부에서의 this
- 함수와 메서드
- 독립성 차이
- 함수 : 자체적으로 독립적 기능 수행
- 메서드 : 자신을 호출한 대상 객체에 관한 동작 수행
var func = function(x) { console.log(this, x); }; //함수 호출 func(1) //Window{...}1 var obj={ method : func }; //메소드 호출 obj.method(2); //{method:f}2 obj['method'](2); //{method:f}2
- 함수 앞 점(.) 또는 대괄호([])로 구분하기
- 메서드 내부에서의 this
- 어떤 함수를 메서드로 호출 시 호출 주체는 함수명 앞의 객체
var obj = { methodA : function() {console.log(this);}, inner : { methodB : function() {console.log(this);} } }; obj.methodA(); //{methodA : f, inner:{...}} ( === obj) obj['methodA']; //{methodA : f, inner:{...}} ( === obj) obj.inner.methodB(); //methodB:f}(=== obj.inner) obj.inner.['methodB'](); //methodB:f}(=== obj.inner) obj.['inner'].methodB(); //methodB:f}(=== obj.inner) obj['inner']['method'];() //methodB:f}(=== obj.inner)
- 함수와 메서드
- 함수로 호출 시 함수 내부에서의 this
- 함수로서 지정할 경우 this 지정 X
- 메서드 내부함수에서 this 우회
- 변수 활용
var obj = { outer : function() { console.log(this); // (1) {outer:f} var innerFunc1 = function () { console.log(this); // (2) Window{ ... } }; innerFunc1(); // 변수명 : _this, that, _,,, var self = this; var innerFunc2 = function() { console.log(self); // (3) {outer:f} }; innerFunc2(); } }; obj.outer();
- this를 바인딩하지 않는 함수
- ES6의 화살표 함수(arrow function)
- 실행 컨텍스트 생성 시 this 바인딩 과정 빠짐
var obj = { outer:function() [ console.log(this); // (1) {outer:f} var innerFunc = () ]> { console.log(this); // (2) {outer : f} }; innerFunc(); } }; obj.outer();
- ⇒ 상위 스코프의 this 그대로 활용
- 실행 컨텍스트 생성 시 this 바인딩 과정 빠짐
- call, apply 메서드를 활용하여 명시적 this 지정 가능
- ES6의 화살표 함수(arrow function)
- 콜백 함수 호출 시 해당 함수 내부의 this
- 콜백 함수의 제어권을 가지는 함수(메서드)가 결정
- 정의하지 않은 경우 전역객체 바라봄
- 생성자* 함수 내부의 this
- 특정 함수가 생성자 함수로 호출된 경우
- ⇒ 내부에서의 this는 새로 만들 인스턴스** 자신이 됨
var Cat = function(name, age) { this.bark = '야옹'; this.name = name; this.age = age; }; var choco = new Cat('초코', 7); var nabi = new Cat('나비', 5); console.log(choco, nabi); /* 결과 Cat { bark : '야옹', name : '초코', age : 7} Cat { bark : '야옹', name : '나비', age : 5} */
- 함수를 호출할 때 결정됨
- : this는 실행 컨텍스트가 생성될 때 결정됨
- 전역 공간에서의 this
- 명시적으로 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 var obj = { a : 1, method : function(x,y) { console.log(this.a, x, y); } }; obj.method(2,3); //1 2 3 obj.method.call({a:4}, 4, 5); // 4 4 5
- Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
- apply 메서드
- call 메서드와 기능적으로 완전히 동일
- 두번째 인자를 배열로 받아 요소들을 호출할 함수의 매개변수로 지정
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
- Function.prototype.apply(thisArg[, argsArray]);
- call.apply 메서드의 활용
- 유사배열객체(array-like object)에 배열 메서드 적용
- 객체에는 배열 메서드 직접 적용 불가
- 배열 메서드 차용 가능한 경우
- 키가 0 또는 양의 정수인 프로퍼티가 존재
- length 프로퍼티의 값이 0 또는 양의 정수인 객체
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에 적용하기
- function a () { var argv = Array.prototype.slice.call(arguments); argv.forEach(function (arg) { console.log(arg); }); } a(1, 2, 3); document.body.innerHTML = '<div>a</div><div>b</div><div>c</div>'; var nodeList = document.querySelectorAll('div'); var nodeArr = Array.prototype.slice.call(nodeList); nodeArr.forEach(function (node) { console.log(node); });
- 문자열에 적용하기
- length 프로퍼티가 읽기 전용이기에 원본 문자열에 변경 가하는 메서드(push, pop, shift, unshift, splice 등)의 경우 에러
- 대상이 반드시 배열이어야 하는 경우(concat) 제대로 된 결과 X
var str = 'abc def'; Array.prtotype.push.call(str, ', pushed string'); //에러 발생 Array.prtotype.concat.call(str, 'string'); //[String {"abc def"}, "string"] Array.prtotype.every.call(str, funtion(char) {return char !== '';}); //false Array.prtotype.some.call(str, funtion(char) {return char === '';}); //true var newArr = Array.prototype.map.call(str, function(char) {return char + '!';}); console.log(newArr); //['a!', 'b!', 'c!', '!', 'd!', 'e!', 'f!'] var newStr = Array.prototype.reduce.apply(str, [ function(string, char, i )) {return string + char + i;}, '' ]); console.log(newStr); //"a-b1c2 3d4e5f6"
- 배열 전환 메서드 Array.from
- ES6에 도입됨
- 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환
var obj = { 0 : 'a', 1 : 'b', 2 : 'c', length : 3 }; var arr = Array.from(obj); console.log(arr); // ['a', 'b', 'c']
- 생성자 내부에서 다른 생성자 호출
- 다른 생성자와 공통된 내용 있을 시 call, apply를 활용해 반복 줄이기 가능
function Person(name, gender) { this.name = name; this.gender = gender; } function Student(name, gender, school) { Person.call(this, name, gender); this.school = shool; } function Employee(name, gender, company) { Person.apply(this, [name, gender]); this.company = company; } var by = new Student('보영', 'female', '단국대'); var jn = new Employee('재난', 'male', '구글');
- 여러 인수를 묶어 하나의 배열로 전달 - apply
- 유사배열객체(array-like object)에 배열 메서드 적용
- call 메서드
//기존 코드
var numbers = [10, 20, 3, 16, 45];
var max = min = numbers[0];
numbers.forEach(function(number) {
if(number > max) {
max = number;
}
if(number < min) {
min = number;
}
});
console.log(max, min); //45 3
//apply 적용
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min); //45 3
//펼치기 연산자(spread operator) 적용
var max = Math.max(...numbers);
var min = Math.min(...numbers);
console.log(max, min); //45 3
- bind 메서드
- ES5 추가됨
- call과 비슷,즉시 호출 X, 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환함
- 새로운 함수 호출 시 인수를 넘기면 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어 등록
- 목적
- 함수에 this를 미리 적용
- 부분 적용 함수 구현
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 6 7
- name 프로퍼티
- bound 접두어
- : bind 메서드를 통해 새로 만든 함수의 name 프로퍼티에 붙음
var func = function (a, b, c, d) { console.log(this, a, b, c, d); }; var bindFunc = func.bind({x:1}, 4, 5); console.log(func.name); // func console.log(bindFunc.name); // bound func
- 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기
- apply, call, bind 메서드 이용
//call 메서드 { var obj = { outer:function() { console.log(this); var innerFunc = function() { console.log(this); }; innerFunc.call(this); } }; obj.outer(); } //bind 메서드 { var obj = { outer : function() { console.log(this); var innerFunc = function() { console.log(this); }.bind(this); innerFunc(); } }; obj.outer(); } //bind메서드 내부함수에 this 전달 { var obj = { logThis : function() { console.log(this); }, logThisLater1 : function() { setTimeout(this.logThis, 500); }, logThisLater2 : function() { setTimeout(this.logThis.bind(this, 1000); } }; obj.logThisLater1(); //Window{...} obj.logThisLater2(); //obj { logThis : f, ...} }
-
- 화살표 함수의 예외사항
- ES6 도입
- 실행 컨텍스트 생성 시 this 바인딩하는 과정 제외 ⇒ 함수 내부에 this 존재 X
- 접근하고자 할 시 스코프체인상 가장 가까운 this에 접근
var obj = { outer : function() { console.log(this); var innerFunc = () => { console.log(this); }; innerFunc(); } }; obj.outer();
- 별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)
- 콜뱀 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우 존재
- 해당 메서드의 thisArg 값을 지정시 콜백 함수 내부에서 this 값을 원하는대로 변경
- 배열 메서드에 많이 포진 ⇒ Set, Map 등
var report = { sum : 0, count : 0, add.function() { var args = Array.prototype.slice.call(arguments); arg.forEach(function(entry) { this.sum += entry; ++this.count; }, this); // 해당 this가 콜백 함수 내부의 this로 바인딩 됨 }, average : function() { return this.sum / this.count; } }; retport.add(60, 85, 95); //add 메서드의 this(report)를 그대로 가리킴 console.log(report.sum, report.count, retport.average()); // 240 3 80
- 이외의 thisArg를 인자로 받는 메서드
- forEach()
- map()
- filter()
- some()
- every()
- find()
- findIndex()
- flatMap()
- from()
- 콜뱀 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우 존재
- 화살표 함수의 예외사항
*생성자 : 구체적인 인스턴스를 만들기 위한 틀
**인스턴스 : 어떤 집합에 대해서 개별적인 요소
***바인딩 : 특정객체에서 실행되게끔 고정시키는 그런 역할
- arguments 객체
- : 함수에 전달된 인수에 해당하는 Array 형태의 객체
반응형
'개발 공부 > JavaScript' 카테고리의 다른 글
클로저 (0) | 2022.07.16 |
---|---|
콜백 (0) | 2022.07.15 |
실행 컨텍스트 (0) | 2022.07.13 |
데이터 타입 (0) | 2022.07.12 |
ES11에 추가된 문법! (0) | 2022.01.28 |