this는 함수가 실행되는 순간에 값이 결정되기 때문에, 어떻게 실행되었는지를 통해 값을 알아내야 한다.
"use strict";
this를 포함한 함수가 실행되는 방식을 확인해야 한다.
var age = 30;
const person = {
age: 20,
printAge: function () {
bar();
//bar()함수는 일반 함수로 실행되었다. 따라서 this는 전역객체이다.
},
};
function bar() {
console.log(this.age);
//이 this의 값이 무엇인지를 알기 위해서는
//this를 가진 bar()가 어디에서 어떤 방식으로 실행되었는지 봐야한다.
}
person.printAge(); //30
//dot notation같아보이지만, 이 함수의 실행방식은 중요하지 않다.
//this를 가진 bar함수를 실행시키는 역할일 뿐이다.
function makePerson(name, age) {
//전역객체로 this값이 설정된다. = age 30
return {
name,
age,
verifyAge: () => {
return this.age > 21;
//화살표 함수는 this를 가지고 있지 않다. 따라서 상위스코프로 올라가 값을 찾는다.
},
};
}
const a = makePerson("ken", 30);
//함수 실행 시점 (일반함수 방식으로 실행)
if (a.verifyAge()) {
alert("Yes, Beer!");
} else {
alert("No, Beer!");
}
var age = 100;
function verifyAge() {
return this.age > 21;
//이 this값을 알기 위해선 this를 포함한 veryfyAGe() 가 실행되는 장소와 방식을 확인해보자.
}
const a = {
age: 20,
verifyAge: verifyAge,
};
const sevenEleven = {
sellBeer: function (customer) {
if (!verifyAge()) {
// verifyAge()는 일반함수 방식으로 실행되었다.
//따라서 this는 전역객체>> age = 100
return "No Beer";
}
return "Beer";
},
};
sevenEleven.sellBeer(a); //Beer
function makePerson(name, age) {
//4. makePerson의 this값을 확인하기 위해서는 이 함수가 실행되는 곳을 찾는다.
return {
name,
age,
verifyAge: () => {
//3. 원래대로라면 30이지만...화살표함수는 this가 없다. 따라서 상위 스코프를 탐색한다.
return this.age > 21;
//1. this값을 알기 위해서는 verifyAge()가 실행된 곳을 찾는다.
},
};
}
const a = makePerson("a", 30);
//5. 일반함수 방식으로 실행되었다. this는 전역객체이다.
//6. 전역 객체에는 age가 없으므로 undefined > undefined>21 = false
if (a.verifyAge()) {
//2. verifyAge는 여기서 실행된다. Dot Notation방식이다.
alert("Yes, Beer!");
} else {
alert("No, Beer!");
}
//No, Beer!
.call 메소드는 첫 번째 인자로 받은 값을 this로 설정하여 함수를 실행한다.
두 번째 인자를 시작으로 나머지 인자들은 해당 함수의 인자로 전달됩니다.
function Animal (name) {
this.name = name;
}
function Human ( name, language) {
Animal.call(this, name) ;
this.language = language;
}
//Animal에서 name값을 받아온다.
function logAge () {
console.log(this.age);
}
const person = {
age : 20
{;
logAge.call(person);
//20
//logAge함수를 실행하는데,this는 person으로 정한다는 의미
logAge()
//undefined
function foo(a,b,c){
console.log(this.age);
console.log(a+b+c);
}
var a = {
age:35
};
foo.call(a,1,2,3,4,5)
//첫번째 인자는 this값
//이후 인자는 매개변수로 쓰인다.
//35
//6
null???
//안 종신
var title = "wow";
const person = {
title : "oh",
getAge : function bar () {
console.log(this.title);
}
};
const people = {
person
};
people[0].getAge.apply(null);
call과 비슷하지만, this값을 결정할 인자 이후 매개변수로 쓰일 인자를 배열의 형태로 입력한다는 차이가 있다.
foo.apply(a, [1,2,3]);
foo.call(a,1,2,3);
Vehicle.apply(this, arguments);
는 Vehicle의 this들을 그대로 받으란 뜻
.call과 .apply는
bind는 call과 apply와 달리 함수를 실행시키지 않는다.
새로운 함수를 반환하고 변수에 담는다.
이 반환된 함수를 직접 실행해야만 메소드가 사용된 원본 함수가 실행된다.
function foo() {
console.log(this.age);
}
var a = {age: 33};
var bar = foo.bind(a);
//bind는 foo를 복제하여 ken을 this값으로 하는 bar라는 새로운 함수를 반환한다.
bar(); //33
//사실 일반함수 형식으로 실행되었지만, bind가 있을 경우에는 우선순위가 바뀌어
//bind의 방식대로 this를 실행한다.
new라는 함수명을 써서 함수를 실행시키는 방법
생성자 함수는 보통 객체를 만들 때 많이 쓴다.
키워드 : 자바스크립트에 내장된 명령어
function foo(){
console.log(this);
//this = {} 와 같은 느낌으로 생각하면 된다.
}
new foo(30); //foo{}
//new를 사용하면 this에 새로운 새 객체가 생성된다.
function foo(){
this.age = 30;
console.log(this);
}
new foo();
//foo {age: 30}
//new 키워드를 사용해 생성된 빈 객체에 30 키 밸류가 들어갔다.
const something = {
age: 10,
speak: function () {
console.log(this.age);
}
};
const butler = {
age: 20,
serve: function (cb) {
cb();
//일반함수 형태로 this값을 포함한 speak function 호출
}
};
butler.serve(something.speak);
//전역에 age라는 변수가 없다.
//serve에서 일반함수로 호출되어 this가 전역객체를 가리키고,
//전역에 age라는 변수가 존재 하지 않아 undefined 반환
function Programmer() {
this.isSmart = false;
this.upgrade = function (version) {
this.isSmart = !!version;
work();
};
return this;
}
function work() {
if (this.isSmart) {
window.alert("I can do my work! I am smart!");
}
}
//일반함수 호출이라 전역객체인데, 전역객체에 issmart변수가 없음 >undefined 반환
const programmer = new Programmer();
programmer.upgrade(1);
const call = {
caller: "mom",
says: function() {
console.log(`Hey, ${this.caller} just called.`);
}
};
let newCall = call.says;
newCall();
//Hey, Undefined just called.
function logThis(){
console.log(this);
}
class myClass {
logThat(){
logThis.call(this)
}
}
const myClassInstance = new myClass()
myClassInstance.logThat()
//myClass{}
Result - The object created by myClass
.Explanation:
logThis
an arrow function? - No.logThis
called with new
? - No.logThis
called with call / apply / bind? - Yes, whatever passed in as first argument. OK, but we are passing this
! what is this
refers to inside the logThat
execution context? Lets check:logThat
an arrow function? - No.logThat
called with new
? - No.logThat
called with call / apply / bind? - No.logThat
called as an object method? - Yes, this
is the object left to the dot - The auto created object inside myClass
in this case.Answer #11
function logThis() {
console.log(this);
}
const btn = document.getElementById('btn');
btn.addEventListener('click', logThis);
//btn
Result - The btn
element.ExplanationThis is a tricky question because we never talked about event handlers attached to DOM
elements. You can look at event handlers that are attached to DOM
elements as if the function is a method inside the element's object, In our case the btn
object. We can look at it as if we did btn.click()
or even btn.logThis()
. Note that this is not exactly whats going on under the hood, but this visualization of the invocation of the handler can help us with the formation of our "mental model" regarding the setting of this
.You can read more about it on the MDN
Now lets walk through the flow:
logThis
an arrow function? - No.logThis
called with new
? - No.logThis
called with call / apply / bind? - No.logThis
called as an object method? - Yes (sort of), in our case btn
is left to the dot.const object = {
message: 'Hello, World!',
logMessage() {
console.log(this.message); // What is logged?
}
};
setTimeout(object.logMessage, 1000);
//undefined
//setTimeout() 함수가 콜백함수를 호출할 때는 일반함수 형태로 호출한다. 따라서 전역변수를 찾고, 전역스코프에 message 변수는 없으므로 undefined를 반환한다.
7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them?
After a delay of 1 second, undefined
is logged to console. Try the demo.
While setTimeout()
function uses the object.logMessage
as a callback, still, it invokes object.logMessage
as a regular function, rather than a method.
And during a regular function invocation this equals the global object, which is window
in the case of the browser environment.
That’s why console.log(this.message)
inside logMessage
method logs window.message
, which is undefined
.
Side challenge: how can you fix this code so that 'Hello, World!'
is logged to console? Write your solution in a comment below!
What logs to console the following code snippet:
const object = {
who: 'World',
greet() {
return `Hello, ${this.who}!`;
},
farewell: () => {
return `Goodbye, ${this.who}!`;
}
};
console.log(object.greet()); // What is logged?
console.log(object.farewell()); // What is logged?
//HEllo, World!
//Goodbye, undefined!
//arrow function이기 때문에 상위 전역 스코프에서 this값을 찾고, 없기 때문에 undefined가 된다