https://www.youtube.com/watch?v=PAr92molMHU
7분 ~ 15분
//this의 5가지 패턴
#1. global reference
this
> window {postMessage: f, blur: f, ....}
//#2 ~ #4에 쓰이는 함수
function bar(){
console.log(this);
}
#2. function invocation
bar()
> window {postMessage: f, blur: f, ....}
#3. method invocation
window.bar()
> window {postMessage: f, blur: f, ....}
#4. construction mode
var barInstance = new bar();
> bar{}
#5. call, apply
//call 사용법
function bar(){
console.log(this);
}
var obj = { hello: 'world'}
bar.call(obj)
> {hello: "world"}
bar.call({a: 1})
>{a: 1}
=======================================
//apply 사용법
var add = function (x, y){
this.val = x + y;
}
var obj = {
val: 0
};
add.apply(obj, [2, 8]);
console.log(obj.val); // 10
add.call(obj, 2, 8);
console.log(obj.val); // 10 // apply는 배열로, call은 쉼표로 넘긴다
------------------------
let arr = [10,2,3,4,7,23]
Math.max.apply(null, arr)
> 23
------------------------
//apply, call 사용시, this를 쓰지 않는 경우
function add(x,y){
return x+y;
}
add.call(null, 2, 8) // this를 쓰지 않을 땐 null로 넘겨줘도 된다.
>10
add.apply(null, [2, 8]) // apply는 배열로
>10
function add(x, y){
this.val = x + y;
console.log(this.val);
}
let obj = { val: 0 };
let boundFn = add.bind(obj, 2, 8);
BoundFn()
#1. call, apply
add.apply(obj, [2, 8]);
//10
add.call(obj, 2, 8);
//10
#2. bind
add.bind(obj, 2, 8);
//function add(x, y){
//this.val = x + y;
//console.log(this.val);
//}
BoundFn() // 10.function invocation처럼 보여서 window가 출력될 것 같지만 이미 this 값이 바인딩 돼있어서 10이 출력된다.
//커링이란 인자 n개를 받는 함수를 인자 1개로 받는 함수로 바꾸는 것.
function template(name, money){
return '<h1>' + name + '</h1><span>' + money + '</span>';
}
>template('hoyong', 1000)
<"<h1>hoyong</h1><span>1000</span>"
let tmplSteve = template.bind(null, 'Steve');
// this 값을 위의 함수에서 사용하지 않았으므로 this를 사용하는 건 의미가 없다. 그래서 null을 넘겨주는 것.
// bind는 함수를 넘겨주고 그 함수의 name에는 'Steve'가 바인딩 되어있다.
>tmplSteve
< function template(name, money){
return '<h1>' + name + '</h1><span>' + money + '</span>';
}
>tmplSteve(100)
<"<h1>Steve</h1><span>100</span>"
>tmplSteve(300)
<"<h1>Steve</h1><span>300</span>"
//bind를 사용해서 인자 하나만 받는 함수들을 만들어냈다(커링)
4분
//function 내에서 this가 window가 아닌 주어진 값으로 적용되게 하는 법.
function member(){
return{
first: 'Ingi',
last: 'Kim',
age: 40,
printDetail: function(){
getSalaryFromServer(function(salary){
console.log(`Name: ${this.first} ${this.last}`);
console.log(`Salary: ${salary}`);
});
}
}
}
>var ingi = member();
<undefined
>ingi
<{first: "Ingi", last: "Kim", age: 40, printDetail: f}
>function getSalaryFromServer(callback){
setTimeout(function(){
callback(10000);
}, 1000);
}
< undefined // 이 콜백함수는 function invocation이다.
> // 1초 후에 callback을 실행, 10000을 넘김
< undefined
> ingi.printDetail()
< undefined
Name: undefined undefined // 이때 this는 window(function invocation이기 때문에). 그래서 상위 오브젝트를 따라가지 않음.
Salary: 10000
어떻게 this.first를 'Ingi', 'Kim'으로 얻어낼 수 있을까.
=================================================
SOLUTION 1: USE bind
function member(){
a return{
first: 'Ingi',
last: 'Kim',
age: 40,
printDetail: function(){
getSalaryFromServer(function(salary){
console.log(`Name: ${this.first} ${this.last}`);
console.log(`Salary: ${salary}`);
}.bind(this));
// bind는 function을 리턴. call,bind는 첫번째로 this를 넘기는데 call은 바로 실행, bind는 this를 가진 채로 function을 리턴.
// 여기서 bind안의 this는 좌측 a부터 z까지의 오브젝트이다. 이 오브젝트가 ${this.first} <- 여기의 this로 바인딩됨. 그래서 해결 가능함.
}
z }
}
=================================================
SOLUTION 2: USE ARROW FUNCTION
function member(){
1 return{
first: 'Ingi',
last: 'Kim',
age: 40,
printDetail: function(){
a getSalaryFromServer((salary) => {
console.log(`Name: ${this.first} ${this.last}`);
console.log(`Salary: ${salary}`);
z });
}
9 }
}
//Arrow Function의 특징은 a부터 z사이에 excution context를 만들지 않는다.
//그렇기에 ${this.first}의 this는 lexical한 상위 오브젝트(1부터 9)를 따라간다.
18분
//Arrow function 내에서의 this
var obj = {
i: 10,
b: () => console.log(this.i, this), // ?
c: function(){
console.log(this.i, this) // ?
}
}
//function은 execution context를 만들고, Arrow function은 자체적으로 execution context를 만들지 않는다.
> obj.b
< undefined// 글로벌 영역에서 this는 window, window.i는 undefined.
Window {postMessage: f, blur: f, ...}// this는 window 그 자체가 될 것.
> obj.c // function expression으로 감쌈. 그렇기에 이만큼({console.log(this.i, this) // ? })의 expression context를 가짐.
< 10 //method invocation의 형식에 따라 this는 obj가 되고, obj.i는 10이 됨.
{i:10, b: f, c: f}//method invocation의 형식에 따라 this는 obj가 됨.
//Arrow function의 construction mode
var Foo = () => {};
var foo = new Foo(); // ?
> Uncaught TypeError: Foo is not a constructor
//Arrow function은 construction mode를 아예 할 수 없음. new 키워드가 필요할 땐 전통적인 function을 쓰거나 class 키워드를 사용.