call,apply,bind & this

남자김용준·2021년 8월 28일
0

call, apply, bind

var example = function(a,b,c){
	return a + b + c;
};
example(1,2,3);
example.call(null,1,2,3);
example.apply(null,[1,2,3]);

함수를 호출하는 세 가지 예시이다.
함수 뒤에 ()를 붙이는 것, call, apply의 방법이 있다.
call은 보통 함수와 똑같이 인자를 넣고, apply는 배열의 형태로 인자를 넣는다. call과 apply가 공통적으로 가진 null은 this를 대체하는 부분이다.

var obj = {
	str: 'zero',
  	f1: function(){
    	alert(this.str);
    }
};

var obj2 = {
	str: 'test'
}

obj.f1(); // zero
obj.f1.call(obj2); // test

마지막 줄에서 this가 가리키는 객체가 obj2로 변했다. f1은 obj에 속한 메서드이지만 call의 context parameter에 obj2를 넣어 this가 가리키는 객체를 변경했다. apply 또한 같은 역할을 한다.

var obj = {
	str: 'zero',
  	f1: function(){
    	alert(this.str);
    }
};

var obj2 = {
	str: 'test'
};

var testFunction = obj.f1.bind(obj2);
testFunction(); // test

bind를 통해서 f1의 this가 obj2로 바뀌었다. call이나 apply와 비슷하지만 함수만 반환하는 형태이다.

this

this의 첫 번째 동작 - 기본 바인딩

크롬 개발자 도구의 콘솔에서 console.log(this)를 쳐보면 window 객체가 나온다.
기본적으로 this는 javascript 실행 환경의 전역 객체를 나타낸다.

함수 안에서 쓴 this

함수 안에서 쓴 this는 2가지 동작을 한다. use strict의 옵션에 따라서 방식이 나뉘는데, 먼저 strict mode가 아닌 경우에서는 아래와 같다.

var num = 0;
function test(){
	this.num = 100;
	num++;
  
  	console.log(num); // 101
  	console.log(this.num); // 101
}

위의 예시에서 this는 window 객체를 가리킨다.

strict mode가 적용된 환경에서는

"use strict"
function test(){
	return this;
}
console.log(test()); // undefined

strict mode에서는 함수 내의 this에 디폴트 바인딩이 없기 때문에 undefined가 된다.

메서드 안에서 쓴 this

메서드 호출 시에는 메서드 내부 코드에서 사용된 this는 해당 메서드를 호출한 객체로 바인딩된다.

var obj = {
	name: 'test',
  	f1: function(){
    	console.log(this.name);
    }
}

obj.f1(); // test

생성자 안에서 쓴 this

생성자 함수가 생성하는 객체로 this가 바인딩된다.

function Person(name){
	this.name = name;
}
let kim = new Person('kim');
console.log(kim.name) // kim

하지만 new 키워드를 사용하지 않으면 일반 함수 호출이기 때문에 this가 window로 바인딩된다.

function Person(name){
	this.name = name;
}
let kim = Person('kim');
console.log(kim.name) // undefined
console.log(window.name) // kim

명시적 바인딩을 한 this

function test(){
	console.log(this);
}

test(); // window

let obj = {
	x: 123
}

test.call(obj); // {x:123}
test.apply(obj); // {x:123}
let test2 = test.bind(obj);
test2() // {x:123}

Arrow 함수에서의 this

화살표 함수는 전역 컨텍스트에서 실행되더라도 this를 새로 정의하지 않고, 바로 바깥 함수나 클래스의 this를 사용한다.

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

위의 코드에선 this가 전역 객체를 가리키고 있어 의도와는 다른 결과가 나왔다.

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

화살표 함수를 사용해 원하는 결과를 얻었다.

profile
frontend-react

0개의 댓글