[JavaScript] JS_ 6. This
# INDEX
1. Values & Data type
2. Operators
3. Control flow
4. Scope & Hoisting
5. Object & Array
6. This
7. Prototype & Inheritance
8. Function
9. Callback function
10. Closuer
11. Class
12. Others
6. This
6-1. this에 대한 기본 개념
- JS에서 함수는, 매개변수로 전달되는 인자값 이외에,
arguments
객체와 this
객체를 암묵적으로 전달 받기 때문에, 모든 함수 내부에서는 (화살표함수 제외) arguments
와 this
를 사용할 수 있음
- JS의
this
키워드는 항상 함수 내부에서 사용됨
- this 값은 this가 사용된 함수가 "어떻게 실행되었는지"에 따라 동적으로 결정됨
- 따라서, this 값을 판별하기 위해서는 함수의 실행문을 찾고 + 해당 함수가 어떻게 실행되었는지를 판별해야 함
6-2. 함수 호출(실행)방식
let foo = function () {console.dir(this);};
1) "일반 함수 호출" (`Regular function call`)
foo(); // window // window.foo();
2) "메소드 호출" ('Dot Notation (Object Method Call)')
let obj = {foo : foo};
obj.foo(); // object // {foo: ƒ}
3) "생성자 함수 호출" ('"new" Keyword')
let instance = new foo(); // instance // foo {}
4) "call / apply / bind 호출" (`call / apply / bind`)
let jazz = { name: 'delilah' };
foo.call(jazz); // Object // name: "delilah"
foo.apply(jazz); // Object // name: "delilah"
foo.bind(jazz)(); // Object // name: "delilah"
6-3. (1) 일반 함수 호출_Regular function call
- 일반 함수 실행 방식의 경우 : 해당 함수의 this 값은 "Global Object" (브라우저에서는 window객체)
- 보통의 경우, this가 window가 되는 것은 버그... (굳이 이렇게 사용하지 않음)
arguments
객체와 this
객체를 암묵적으로 전달 받기 때문에, 모든 함수 내부에서는 (화살표함수 제외) arguments
와 this
를 사용할 수 있음this
키워드는 항상 함수 내부에서 사용됨let foo = function () {console.dir(this);};
1) "일반 함수 호출" (`Regular function call`)
foo(); // window // window.foo();
2) "메소드 호출" ('Dot Notation (Object Method Call)')
let obj = {foo : foo};
obj.foo(); // object // {foo: ƒ}
3) "생성자 함수 호출" ('"new" Keyword')
let instance = new foo(); // instance // foo {}
4) "call / apply / bind 호출" (`call / apply / bind`)
let jazz = { name: 'delilah' };
foo.call(jazz); // Object // name: "delilah"
foo.apply(jazz); // Object // name: "delilah"
foo.bind(jazz)(); // Object // name: "delilah"
Non Strict Mode : Global Object
var age = 30; //글로벌 객체 // 5. 이 경우에는 this가 window
var person = {
age: 20,
printAge: function () {
bar(); // 3. 해당 함수의 실행문 찾기 // 4. 실행문의 형태에 따라 this의 값 결정
}
};
function bar () { // 2. this가 포함된 함수 찾기
console.log(this.age); //30 // 1. 먼저 this찾기
}
person.printAge();
Strict Mode : undefined
'use strict';
var name = 'delilah';
function foo () {
console.log(this.name); //can not read property 'name' of undefined at foo
}
foo();
6-4. (2) 메소드 호출_Dot Notation (Object Method Call)
- dot notation 을 이용하여 함수를 실행할 경우 : 해당함수 내부의 this는 함수실행문에서 "Dot앞에 놓인 객체"를 뜻함
- tip!! dot notation은 실행문을 보고 하나하나 찾아나가는 것이 핵심!
var age = 100;
var delilah = {
age : 35,
foo : function foo () {
console.log(this.age); //console.log(delilah.age) 와 같은 의미 //35
}
};
delilah.foo(); //함수 실행문 here! => 실행문 앞에 .(dot)이 위치하며, 그 부분은 객체 delilah 되므로 this는 delilah
--------------------------------------------------------------------------------------------
var age = 100;
var delilah = {
age : 35,
foo : function bar () {
console.log(this.age); // 아래 호출방식에 따라 값이 달라짐
}
};
var willy = {
age : 31,
foo : delilah.foo
};
var foo = delilah.foo; // 이거는 함수
delilah.foo(); //35
willy.foo(); //31
foo(); //100 (window)
--------------------------------------------------------------------------------------------
// 어렵지만 차근차근... ㅎㅎㅎ
var age = 100;
function verifyAge () { // 2.함수 verifyAge의 내부함수이다
return this.age > 21; // 1.this를 찾는다 //8. 20>21의 return value = false
}
var delilah = {
age : 20, // 7.delilah(.dot)age는 20
verifyAge : verifyAge
};
var sevenEleven = {
sellBeer : (customer) => { // 5.this는 매개변수 customer
if (!(customer.verifyAge())) { // 3.verifyAge의 실행문을 찾는다 // 4.customer(매개변수)가 this객체가 된다
return "No beer"; // 9.verifyAge가 false => 의 반대는 => true => 따라서, 출력1 ("No beer")
} else {
return "Beer";
}
}
}
sevenEleven.sellBeer(delilah); // 6.변수sevenEleven의 프로퍼티 sellBeer에서 매개변수 delilah // 10.따라서, return "Beer"
--------------------------------------------------------------------------------------------
function makePerson (name, age) { // 2. 이 makePerson의 실행결과는 {}객체 => 이것이 delilah가 된다
return {
name,
age,
verifyAge: () => { // 4. 여기! // 6. BUT! 여기는 현재 '화살표함수' 따라서, this가 없음
return this.age > 21; // 4. 여기! // 6. this를 찾아 올라가면 함수 makePerson을 찾을 수 있다
} // 9. 따라서, 이 this는 global obj // 10. 결과적으로 undefined>21 는 false
};
}
const delilah = makePerson("delilah", 30); // 1. delilah라는 변수에 담기는 것은? 함수 makePerson의 실행결과 // 7. makePerson의 실행 // 8. 어떻게 실행? 일반함수
if (delilah.verifyAge()) { // 3. delilah.verifyAge 가 가르키는 것은? // 5. 4번의 함수를 여기서 실행!
alert("Yes, Beer!");
} else {
alert("No, Beer!"); // 11. 따라서, false값을 출력! ("No, Beer!")
}
--------------------------------------------------------------------------------------------
6-5. (3) 생성자 함수 호출_new Keyword
- 프로토타입과 이어지는 문맥
- 새로운 빈 객체가 this로 할당됨
- 생성자 호출은 객체.메소드() 과 같이 객체 내에 메소드를 호출하는 방법과 비슷하지만, 객체가 new 키워드를 이용해서 만들어졌다는 것이 다름. 이 때의 객체를 인스턴스라고 함 /
인스턴스.메소드()
class Counter {
constructor() {
this.value = 0; // 생성자 호출을 할 경우, this는 new 키워드로 생성한 Counter의 인스턴스입니다
}
increase() {
this.value++
}
decrease() {
this.value--
}
getValue() {
return this.value
}
}
let counter1 = new Counter() // 생성자 호출
counter1.increase()
counter1.getValue() // 1
-----------------------------------------------------------------------
function foo () {
// this = {}; =>라고 생각하면 쉬움
console.log(this) // foo {}
}
new foo(); // foo () = {}
-----------------------------------------------------------------------
function foo () {
// this = {}; =>라고 생각하면 쉬움
this.age = 30;
this.logName = function () {console.log("name")}; // 처럼 만들어줄 수도 있음
console.log(this)
}
new foo(); // foo () = {}
6-6. (4) call / apply / bind 호출
- 모든 JS 객체에는 내장되어 있는 메소드를 쓸 수 있음 (toString, slice, push, pop 등등)
- 함수도 객체, 배열도 객체이기 때문에 메소드를 쓸 수 있음
- 함수에도 내장되어 있는 메소드가 따로 있음 (.call .apply .bind 도 그 중에 하나)
- 함수는 단순히 소괄호를 열고 닫는 방법 () 외에도, 메소드를 이용해 실행할 수 있음 (ex. foo( ) or foo.call( ) )
1) Funcion.prototype.call
- .call, .apply 호출은 명시적으로 this를 지정하고 싶을 때 사용
- 첫 번째 인자로 받은 값을 해당 함수의 this로 설정하여 함수를 실행
- 두 번째 인자부터 ~ 나머지 인자들은, 해당 함수의 인자로 전달됨
- .call 메소드는 받을 수 있는 인자의 갯수 제한이 없음
- 메소드가 사용된 함수를 실행시킴
function foo() {} // foo함수 생성
foo(); // foo함수 실행
foo.call(); // foo함수에 call이라는 메소드를 이용해 호출
foo.call(person); // foo함수를. 실행하려고 하는데. this를 person값으로 해!
// ex)
function logAge () {
console.log(this.age); // 20
}
const person = {
age: 20
};
logAge.call(person); // call메소드가 실행된 함수logAge를 실행하는데, 인자를 person으로 지정
위의 예제에서 logAge.call(person) 구문의 2가지 기능!!
(1) logAge 함수의 this를, 첫 번째 인자로 받은 person으로 설정한다.
(2) logAge 함수를 실행한다. (함수 내부 구문들이 실행된다.)
------------------------------------------------------------------
// ex)
let status = "선글라스";
setTimeout(()=> {
const status = "하트";
const data = {
status : "아보카도",
getStatus : function () {
return this.status;
}
};
console.log(data.getStatus());
//"아보카도" //data.status가 된다
console.log(data.getStatus.call(this));
//"선글라스"
//getStatus함수의 this를 인자this로 설정한 후 실행.
//but, 해당함수는 화살표인자라 undefined가 되어, 밖으로 나가 global obj로!
},1000);
2) Function.prototype.apply
- .call, .apply 호출은 명시적으로 this를 지정하고 싶을 때 사용
- 첫 번째 인자로 받은 값을 해당 함수의 this로 설정하여 함수를 실행
- 두 번째 인자는 반드시 "배열"이여야 하며, 해당 배열의 요소들이 해당 함수의 인자로 전달됨
- 기본적으로 .call 메소드와 매우 유사하지만, 단지 "두개의 인자"만을 받을 수 있음
- call보다 동적인 상황에 좀 더 어울림
- 메소드가 사용된 함수를 실행시킴
(인자의 개수가 매개변수보다 모자란 경우, NaN)
(인자의 개수가 매개변수보다 많은 경우, 마지막 인자는 무시) spread operator
의 도입으로 굳이 apply를 이용할 필요가 없어짐
ex.Math.max(...[5,4,1,6,2]) // 6
// 간단한 call과 apply의 쓰임의 차이점
function add(x,y) {
return this+x+y;
}
add.call(1,2,3)// 6
----------------------------------------
function add(x,y) {
return this+x+y;
}
add.call(1,[2,3])// 6
3) Function.prototype.bind
- bind가 일반함수호출보다 strong
- 첫번째 인자는 this, 두번째 인자부터는 필요한 파라미터를 전달
function.bind (this값, 인자1, 인자2, ...)
- .bind는 .call과 유사하게 this 및 인자를 바인딩하나, 당장 실행하는 것이 아닌 바인딩된 함수를 리턴하는 함수
- bind메소드는 원본 함수를 복제한 "새로운 함수"를 반환
- call 메소드와 유사하게, 받을 수 있는 인자의 갯수에 대한 제한이 없음
function foo () {
console.log("hello");
}
const bar = foo.bind(); // .bind 메소드는 새로운 "함수"를 반환 O && 실행 X
foo.bind()(); // 위와 동일값 / 조금 이상... 따라서 보통 변수를 따로 설정해준다
bar(); // 이제 bar에는 함수가 담겼기 때문에, bar()로 실행해주어야 한다
bar; // function foo () {console.log("hello")} 를 반환
// 복제를 한 후, 복제된 함수를 실행해야, 기존의 foo 함수를 실행 할 수 있다.
------------------------------------------------------------------------------------------------
function foo (a,b,c) {
console.log(this.age); // 35 // this에 delilah // console.log(delilah.age);
console.log(a+b+c); // 6
}
const delilah = {
age : 35
};
const bar = foo.bind(delilah,1); // bar = function foo 이며, this에 delilah이 들어가고, 인자로 1
bar(2,3);
------------------------------------------------------------------------------------------------
function foo (a,b,c,d,e,f) {
console.log(this.age);
console.log(a+b+C+d+e+f);
}
const delilah = {
age : 35
}; // 1->a, 2->b, 3->c.
const bar = foo.bind(delilah,1,2,3); // 변수bar에는 함수foo가 담기며, this는 delilah, 인자로는 abc에 각각 123.
bar(4,5,6); // 4->d, 5->e, 6->f.
** bind / new / 인스턴스 / prototype
Author And Source
이 문제에 관하여([JavaScript] JS_ 6. This), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@delilah/JavaScript-JS-6.-This저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)