This #4
Replies: 4 comments
-
3-1-3 함수로서 호출할 때 그 함수 내부에서의 this함수 내부에서의 this어떤 함수를 함수로서 호출한 경우에는 this가 지정되지 않습니다. this에는 호출한 주체에 대한 정보가 담깁니다. 그런데 함수로서 호출하는 것은 호출 주체(객체지향 언어에서의 객체)를 명시하지 않고 개발자가 코드에 직접 관여해서 실행한 것이기 때문에 호출 주체의 정보를 알 수 없는 것입니다. 2장(#3) 에서 실행컨텍스트를 활성화할 당시에 this가 지정되지 않은 경우 this는 전역 객체를 바라본다고 했습니다. 따라서 함수에서의 this는 전역 객체를 가리킵니다. 더글라스 크락포드는 이를 명백한 설계상의 오류라고 하였습니다.
메서드 내부함수에서의 this3-1-2에서 우리는 어떤 함수를 함수로서 호출했는지 메서드로서 호출했는지만 알면 this의 값을 정확히 알 수 있다는 것을 배웠습니다. 아래는 어떤 결과가 나올까요? var obj1 = { // 1번째 줄
outer: function () { // 2번째 줄
console.log(this); // 3번째 줄
var innerFunc = function () { // 4번째 줄
console.log(this); // 5번째 줄
}; // 6번째 줄
innerFunc(); // 7번째 줄
// 8번째 줄
var obj2 = { // 9번째 줄
innerMethod: innerFunc, // 10번째 줄
}; // 11번째 줄
obj2.innerMethod(); // 12번째 줄
}, // 13번째 줄
}; // 14번째 줄
obj1.outer(); // 15번째 줄
여기서 알 수 있는 점은 같은 함수임에도 7번째 줄처럼 호출되었느냐 12번째 줄처럼 호출되었느냐에 따라 바인딩되는 this의 대상이 서로 달라진다는 점입니다. 결론 this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지 없는지가 관건인 것입니다. 3-1-4 콜백 함수 호출 시 그 함수 내부에서의 this함수 A의 제어권을 다른 함수(또는 메서드) B에게 넘겨주는 경우 함수 A를 콜백 함수라고 합니다. 콜백 함수도 함수이기 때문에 기본적으로 this가 전역 객체를 참조합니다. 만약 제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정하는 경우에는 그 대상을 참조합니다. <!DOCTYPE html>
<html lang="en">
<body></body>
<script>
setTimeout(function () {
console.log(this); // (1)
}, 300);
[1, 2, 3, 4, 5].forEach(function (x) {
console.log(this, x); // (2)
});
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function (e) {
console.log(this, e); // (3)
});
</script>
</html>
3-1-5 생성자 함수 내부에서의 this생성자 함수는 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수입니다. 객체지향 언어에서는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스라고 합니다. 프로그래밍적으로 ‘생성자’는 구체적인 인스턴스를 만들기 위한 일종의 틀입니다. 자바스크립트는 함수에 생성자로서의 역할을 함께 부여했는데요, new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작하게 됩니다. 그리고 어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 됩니다. var Cat = function (name, age) {
this.bark = '야옹';
this.name = name;
this.age = age;
};
var choco = new Cat('초코', 7); // (1)
var nabi = new Cat('나비', 5); // (2)
console.log(choco, nabi); |
Beta Was this translation helpful? Give feedback.
-
자바스크립트에서 this는 실행 컨텍스트가 생성될 때 함께 결정된다. (<=> 실행컨텍스트는 함수를 실행할 때 생성되므로, this는 함수를 호출할 때 결정된다.) 3-1-1 전역 공간에서의 this전역 컨텍스트를 생성하는 주체가 전역 객체이기 때문에, 전역 공간에서 this는 전역 객체를 가르킨다. 역사적으로 전역 객체에 접근하려면 다른 JavaScript 환경에서 다른 구문이 필요했다.
이에 ES11에 globalThis가 생겨났으며 // 브라우저 환경
console.log(this === window, this === globalThis) // true true 전역 변수와 전역 객체의 삭제var a = 1;
delete window.a; // false
console.log(a, window.a, this.a) // 1 1 1 window.b = 2;
delete window.b; // true
console.log(b, window.b, this.b) // VM222:1 Uncaught ReferenceError: b is not defined 3-1-2 메서드로서 호출할 때 그 메서드 내부에서의 this어떤 함수를 실행하는 방법은 여러가지가 있는데, 가장 일반적인 방법 두 가지는 함수로서 호출하는 경우와 메서드로서 호출하는 경우이다. 이 둘을 구분하는 유일한 차이는 독립성이다. 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다. 자바스크립트는 상황별로 this 키워드에 다른 값을 부여하게 함으로써 이를 구현했다.
쉽게 말해 앞에 |
Beta Was this translation helpful? Give feedback.
-
3-2-5 화살표 함수의 예외사항ES6에 새롭게 등장한 화살표 함수 내부에는 this가 없다. 내부에 this가 없다는 것은 화살표 함수에서 this에 접근할 때는 스코프 체인상 가장 가까운 this에 접근하게 된다는 의미다. 일반 함수아래 예제에서 innerFunc를 일반 함수로 정의할 경우, innerFunc내 this는 global이다. var obj = {
outer: function () {
console.log(this); //this: outer
var innerFunc = function () {
console.log(this); // this: global
};
innerFunc();
},
};
obj.outer(); 화살표 함수하지만 innerFunc를 화살표 함수로 정의할 경우, innerFunc내 this는 outer이다. 상위 스코프의 this를 가리키기 때문이다. var obj = {
outer: function () {
console.log(this); //this: outer
var innerFunc = () => {
console.log(this); //this : outer
};
innerFunc();
},
};
obj.outer(); 화살표 함수가 혼동을 주는 경우 (일반 함수 사용시 정상 동작)1,. 메서드로 사용할 때const person = {
name: 'Lee',
sayHi: () => console.log(`Hi ${this.name}`)
};
person.sayHi(); // Hi undefined 위 예제에서는 화살표 함수를 사용한 메서드 sayHi가 person을 가리키지 않고 상위 스코프 global this를 가리킨다. 2. prototype에 할당할 때화살표 함수로 정의된 메소드를 prototype에 할당하는 경우도 동일한 문제가 발생한다. // Bad
const person = {
name: 'Lee',
};
Object.prototype.sayHi = () => console.log(`Hi ${this.name}`);
person.sayHi(); // Hi undefined 3. 생성자 함수화살표 함수는 생성자 함수로 사용할 수 없다. 생성자 함수는 prototype 속성을 가져야하고, prototype 속성이 가리키는 prototype 객체의 constructor를 사용해야 하지만 화살표 함수는 prototype 속성을 가지고 있지 않기 때문이다. const Foo = () => {};
// 화살표 함수는 prototype 프로퍼티가 없다
console.log(Foo.hasOwnProperty('prototype')); // false
const foo = new Foo(); // TypeError: Foo is not a constructor 4. addEventListener 함수의 콜백 함수addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면 this가 상위 컨택스트인 전역 객체 window를 가리킨다. 화살표 함수//화살표 함수
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
}); 일반 함수일반 함수로 정의된 addEventListener 함수의 콜백 함수 내부의 this는 이벤트 리스너에 바인딩된 요소(currentTarget)를 가리킨다. //일반 함수
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
}); 3-2-6 별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)콜백 함수를 인자로 받는 메서드 중 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 메서드가 있다. 이런 메서드는 배열 메서드에 많이 존재하며, Set, Map 등의 메서드에서도 일부 존재한다. 콜백 함수와 함께 thisArg를 인자로 받는 메서드
Array.prototype.forEachvar report = {
sum: 0,
count: 0,
add: function () {
var args = Array.prototype.slice.call(arguments);
args.forEach(function (entry) {
this.sum += entry; //forEach의 두 번째 인자로 전달한 this⭐️ 가 바인딩 된다. (report)
++this.count;
}, this); // /forEach의 두 번째 인자로 this⭐️ 전달 (report)
},
average: function () {
return this.sum / this.count;
},
};
report.add(60, 85, 95);
console.log(report.sum, report.count, report.average()); // 240 3 80 add 메서드
만약 두 번째 인자로 this를 전달하지 않았다면?
|
Beta Was this translation helpful? Give feedback.
-
명시적으로 this를 바인딩 하는 방법 3-2-1 call 메서드Function.prototype.call(thisArg[, arg1[, arg2[, ...]]]) call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다. call 메서드의 첫 번째 인자를 this로 바인딩, 이후 인자들을 호출할 함수의 매개변수로 사용한다. 기본적으로 함수의 this는 전역객체를 참조하지만, call 메서드 사용시 임의의 객체를 명시적으로 this로 지정할 수 있다. 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 3-2-2 apply 메서드Function.prototype.apply(thisArg[, argsArray]) apply 메서드도 call 메서드와 기능적으로 동일하다. 다만, 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 3-2-3 call/apply 메서드의 활용
call/apply 메서드를 사용하는 방법은 this를 원하는대로 바인딩 가능하다는 점에서 유용하지만, this를 예측하기 어렵다는 점에서 가독성을 떨어뜨리는 단점이 존재한다. 하지만 ES5이하의 환경에서 대안이 없기 때문에, 광범위하게 이용되고 있다. 3-2-4 bind 메서드Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]]) bind 메서드는 ES5에서 추가된 기능이다. call과 유사하지만 호출하지 않고 지정된 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
// this를 미리적용
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
+aglobalThis가 뭐임? |
Beta Was this translation helpful? Give feedback.
-
이번주 주제는 this 입니다. 아래 주제 중 1개를 선택하여 생성해주세요.
주제 1
3-1-1 전역 공간에서의 this
3-1-2 메서드로서 호출할 때 그 메서드 내부에서의 this
주제2
3-1-3 함수로서 호출할 때 그 함수 내부에서의 this
3-1-4 콜백 함수 호출 시 그 함수 내부에서의 this
3-1-5 생성자 함수 내부에서의 this
주제3
3-2-1 call 메서드
3-2-2 apply 메서드
3-2-3 call / apply 메서드의 활용
3-2-4 bind 메서드
주제4
3-2-5 화살표 함수의 예외사항
3-2-6 별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)
주제5
this 관련 자유주제
Beta Was this translation helpful? Give feedback.
All reactions