JavaScript의 this
■ Js This의 범위
1) 영향을 주는 것
(a) 엄격 / 비엄격
엄격 / 비엄격은 global 또는 block 안에서 각각 선언할 수 있음
(b) 함수의 호출방식
(c) 화살표 함수 사용 여부
2) this의 정의
실행 컨텍스트( global, function, eval )에 따라 달라짐
또한 엄격 / 비엄격에 대해서 다음과 같음
비엄격 모드 | 엄격 모드 | |
this | 항상 객체 | 그 어떤 값도 가능 |
※ 실행 컨텍스트이므로, runtime때 dynamic하게 바뀜!
■ 문맥
1) 기본 바인딩 - 전역 문맥
global execution context, this는 엄격 / 비엄격 모드 관계 없이 전역 객체 참조
// 웹 브라우저에서는 window 객체가 전역 객체
console.log(this === window); // true
a = 37;
console.log(window.a); // 37
this.b = "MDN";
console.log(window.b) // "MDN"
console.log(b) // "MDN"
2) 함수 문맥
함수 안에서의 this는 함수의 주인에게 바인딩 됨.
(a) 비엄격 모드
> this의 값이 호출에 의해 설정되지 않았음
function f1() {
return this;
}
// 브라우저
f1() === window; // true
// Node.js
f1() === global; // true
(b) 엄격모드
> this 값이 실행 문맥에 진입( global scope이 아닌 block으로 )
> default 바인딩이 없어서 undefined 결과 생김
function f2(){
"use strict"; // 엄격 모드 참고
return this;
}
f2() === undefined; // true
3) 매써드 문맥 - 객체의 매써드
함수가 객체의 매써드로 사용되어 호출되면, 그 해당함수 내부에서의 this는 호출한 객체
var person = {
firstName: 'John',
lastName: 'Doe',
fullName: function () {
return this.firstName + ' ' + this.lastName; //this 는 person
},
};
person.fullName(); //"John Doe"
> 외부에서 정의된 함수를 불러와도 this가 context때문에 변경 됨
var num = 0;
function showNum() {
console.log(this.num);
}
showNum(); //0
var obj = {
num: 200,
func: showNum,
};
obj.func(); //200
> 매써드 안의 내부 함수의 경우 this 바인딩이 다름
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
}
bar();
}
};
obj.foo();
> 매써드의 내부함수 binding work-around 방법
var value = 1;
var obj = {
value: 100,
foo: function() {
var that = this; // Workaround : this === obj
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
console.log("bar's that: ", that); // obj
console.log("bar's that.value: ", that.value); // 100
}
bar();
}
};
obj.foo();
4) Event hander 문맥
> 3의 메써드 문맥의 연장선
var btn = document.querySelector('#btn')
btn.addEventListener('click', function () {
console.log(this); //#btn
});
5) 생성자 문맥
new 키워드를 통해 생성했을 시 "생성자 함수" 객체에 this가 binding 됨
function Person(name) {
this.name = name;
}
var kim = new Person('kim');
var lee = new Person('lee');
console.log(kim.name); //kim
console.log(lee.name); //lee
※ new를 쓰지 않으면 일반 함수와 다를 것이 없으므로, window로 this가 binding 됨
var name = 'window';
function Person(name) {
this.name = name;
}
var kim = Person('kim');
//전역 window의 프로퍼티 name의 변경
console.log(window.name); //kim
6) Arrow function의 this
추가 참조 : Link
Arrow function의 this는 항상 정적으로 상위 scope의 this를 가르킨다 (lexical this)
const Person = () => {
this.age = 0;
console.log(this.age); // 0
setTimeout(() => {
this.age++; // 1
console.log(this.age); // 1
}, 1000);
}
Person();
>>>
1
7) 명시적 binding의 this
apply, call, bind 매써드
- apply : Obj + array
- call : Obj + param
- bind : Obj + tuple param for function activation
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar(a, b) {
console.log("bar's this: ", this); // obj
console.log("bar's this.value: ", this.value); // 100
console.log("bar's arguments: ", arguments);
}
// 내부함수로 호출이지만, 명시적으로 binding 해줘서 this가 obj로 바뀜
bar.apply(obj, [1, 2]);
bar.call(obj, 1, 2);
bar.bind(obj)(1, 2);
}
};
obj.foo();
※ bind 매써드
추가 참조 : developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Function.prototype.bind() - JavaScript | MDN
Function.prototype.bind() bind() 메소드가 호출되면 새로운 함수를 생성합니다. 받게되는 첫 인자의 value로는 this 키워드를 설정하고, 이어지는 인자들은 바인드된 함수의 인수에 제공됩니다. func.bin
developer.mozilla.org
> bind에 thisArg로 binding할 this 이외의 arg들은 해당 함수 앞에 차례로 argument로 들어가게 됨
> binding 예시
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// 선행될 인수를 설정하여 함수를 생성합니다.
var leadingThirtysevenList = list.bind(null, 37); //list라는 함수 인자 맨 앞에 37 추가
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
> 활용 방법
(1)예시로 동일한 매써드 존재할 때
// 다음과 같이 겹치는 property가 있을 때
function Character(name, level) {
this.name = name;
this.level = level;
}
function Player(name, level, job) {
this.name = name;
this.level = level;
this.job = job;
}
function Character(name, level) {
this.name = name;
this.level = level;
}
function Player(name, level, job) {
Character.apply(this, [name, level]); // binding을 new를 사용하여 Player의 this에 binding 하여
// Character 의 this가 Player의 this로 치환됨
// Property가 같아서 이런식으로 사용가능
this.job = job;
}
var me = new Player('Nana', 10, 'Magician');
(2) 유사 array의 array화
> 원래는 error 때문에 array 매써드들 사용 못함
// Error case
function func(a, b, c) {
console.log(arguments);
arguments.push('hi!'); //ERROR! (arguments.push is not a function);
}
// No-error case
function func(a, b, c) {
var args = Array.prototype.slice.apply(arguments);
args.push('hi!');
console.dir(args);
}
func(1, 2, 3); // [ 1, 2, 3, 'hi!' ]
7) 화살표 함수와 this
전역 컨텍스트에서 실행되더라도, 부모 함수 / 생성자 함수(클래스)의 this로 바인딩 됨
> Error case
var Person = function (name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this); // Person {name: "Nana", age: 28}
setTimeout(function () {
console.log(this); // Window
console.log(this.name + ' is ' + this.age + ' years old');
}, 100);
};
};
var me = new Person('Nana', 28);
me.say(); //global is undefined years old ///////// <- not wanted case
> Right case
var Person = function (name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this); // Person {name: "Nana", age: 28}
setTimeout(() => {
console.log(this); // Person {name: "Nana", age: 28}
console.log(this.name + ' is ' + this.age + ' years old');
}, 100);
};
};
var me = new Person('Nana', 28); //Nana is 28 years old
참조 :
developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
this - JavaScript | MDN
this JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 또한 엄격 모드와 비엄격 모드에서도 일부 차이가 있습니다. 대부분의 경우 this의 값은 함수를 호출한 방법에 의해
developer.mozilla.org
javascript this의 4가지 동작 방식
이번 글에서는 자바스크립트 this가 어떻게 동작하는지 알아보겠습니다. 프로토타입을 먼저 쓸지, this를 먼저 쓸지 고민했는데 아무래도 this가 좀 더 쉬울 것 같네요 1. 오해 흔히(java에서) 클래
yuddomack.tistory.com
[JS] 자바스크립트에서의 this
this는 이것을 뜻합니다! (그러니까 '이게' 뭐죠...... 😵) 자바스크립트 내에서 this는 '누가 나를 불렀느냐'를 뜻한다고 합니다. 즉, 선언이 아닌 호출에 따라 달라진다는 거죠. 그럼 각 상황별로 th
nykim.work
this | PoiemaWeb
자바스크립트의 this keyword는 Java와 같은 익숙한 언어의 개념과 달라 개발자에게 혼란을 준다. Java에서의 this는 인스턴스 자신(self)을 가리키는 참조변수이다. this가 객체 자신에 대한 참조 값을
poiemaweb.com