[TIR] this

THIS

자바 스크립트에서 함수를 호출할 때, 매개변수로 전달되는 인자 외에 arguments 객체와 this를 암묵적으로 전달받게 됩니다. 이 때 브라우저는 Window객체를 가르킵니다.

  • 크롬 개발자 도구에서 this를 출력했을 때

  • 함수와 화살표 함수에서 this를 출력했을 때

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

const arrow = () => {
  console.log(this);
}

normal(); //Window {0: Window, window: Window, self: Window, …}
console.log(arrow()); //Window {0: Window, window: Window, self: Window, …}

함수 호출 패턴에 따른 this

자바 스크립트는 함수 호출 패턴에 따라서 this에 바인딩 되는 객체가 달라지게 됩니다.

함수 호출

전역 변수는 모두 Window 객체의 프로퍼티가 됩니다. 기본적으로 함수에 작성된 this는 전역 객체에 바인딩 됩니다. 또한 함수 안에 있는 내부 함수 또한 전역객체에 바인딩됩니다.

    function func(){
        console.log(`Functhis: ${this}`) //Functhis: [object Window]

    	function inFunc(){
            console.log(`inFunc this: ${this}`) //inFunc this: [object Window]
    	}
    	
    	inFunc();
    }

    func();

메소드 호출

메소드 내부에 있는 this는 해당 메소드를 소유하고 있는 객체에 바인딩합니다.

    const english = {
    	lan: 'hi',
    	greeting: function(){
    		console.log(this === english) 
    		console.log(this.lan) 
    	}
    };

    english.greeting(); //true hi

    const korean = {
    	lan: '안녕'
    };

    korean.greeting = english.greeting; //이때 this는 korean에 바인딩
    korean.greeting(); // false 안녕

그렇지만 메소드 내부에 있는 함수의 this는 전역객체를 가르키게 됩니다.

    var lan = '안녕';

    const english = {
    	lan: 'hi',
    	greeting: function(){
    		function hi() {
    			console.log(`hi's this: ${this}`); //hi's this: [object Window]
    			console.log(`hi's this value: ${this.lan}`); //hi's this value: undefined
    		}

    		hi();
    	}
    };

    english.greeting();

생성자 호출

new 연산자를 이용해 생성자 함수를 호출하면 빈객체를 생성하고 this를 바인딩한 후 this를 통한 프로퍼티를 생성하여 생성된 객체 반환합니다.

   function Language(l){
       this.l = l;
   }

   const korean = new Language('안녕');
   console.log(korean.l); //안녕

   const english = new Language('hey');
   console.log(english.l); //hey

   const chinese = Language('你好');
   console.log(window.l); //你好

call(), apply(), bind() 호출

call

callthis값과 전달된 인수와 함께 함수를 호출합니다.
call은 객체의 생성자 연결할 때, 익명함수 호출, 함수 호출 및 문맥 지정, 첫번째 인수 지정없이 함수 호출 등에 사용됩니다.

1) 객체의 생성자 연결

function Person(name, age) {
  this.name = name;
  this.age = age;
}

function Jenna(name, age) {
  Person.call(this, name, age);
  this.sex = 'female';
}

console.log(new Jenna('jenna', 26).name); //"jenna"

2) 익명함수 호출

const people = [
  { name: 'Jenna', age: 26 },
  { name: 'Semo', age: 29 }
];

for (let i = 0; i < people.length; i++) {
  (function(i) {
    const introduce = function() {
      console.log(`Hello guys! I'm ${this.name} and I'm ${this.age}.`);
    }
    introduce();
  }).call(people[i]);
}

3) 함수 호출 및 문맥 지정

function greet() {
	console.log(`Hello! I'm ${this.name} and I like ${this.likes}.`);
}

const person = { name: 'Olaf', likes: 'warm hugs' };

greet.call(person); //"Hello! I'm Olaf and I like warm hugs."

4) 첫번째 인수 지정없이 함수 호출
하지만 엄격 모드에서는 this는 undefined를 가집니다.

const name = 'Olaf';

function reply(){
  console.log('Hello', this.name);
}

reply.call(); // "Hello Olaf"

apply

applythis값과 배열(유사 배열 객체)로 제공되는 함수를 호출합니다.
apply는 배열에 배열을 더할 때, 내장함수와 함께 사용할 때, 생성자 체이닝할 때 등에 사용됩니다.

1) 배열에 배열을 더할 때

const upper = ['A', 'B'];
const lower = ['a', 'b'];
upper.push.apply(upper, lower);
console.log(upper); // Array ["A", "B", "a", "b"]

2) 내장함수와 함께 사용할 때

const nums = [5, 6, 2, 3, 7];
let max = Math.max.apply(null, nums);
let min = Math.min.apply(null, nums);
max = -Infinity, min = +Infinity;

for (let i = 0; i < nums.length; i++) {
  if (nums[i] > max) {
    max = nums[i];
  }
  if (nums[i] < min) {
    min = nums[i];
  }
}

console.log(max, min); //7 2

bind

bind가 호출되면 새로운 함수를 생성합니다. 받게되는 첫 인자의 value로는 this키워드를 설정하고 나머지 인자들은 바인드된 함수의 인수에 제공합니다.
bind는 크게 바인딩된 함수 생성, 부분 적용 함수, sestTimeout함수, 생성자로 쓰이는 바인딩된 함수 등에 사용됩니다.

1) 바인딩된 함수 생성

var x = 9;
var module = {
  x: 5,
  getX: function() { console.log(this.x); }
};

module.getX(); // 5
var retrieveX = module.getX;
retrieveX(); // 9 
var boundGetX = retrieveX.bind(module);
boundGetX(); // 5

2) 부분 적용 함수

function list() {
  return Array.prototype.slice.call(arguments);
}

const list1 = list(1, 2, 3); // Array [1, 2, 3]

const leadingThirtysevenList = list.bind(null, 37);
const list2 = leadingThirtysevenList();  // Array [37]
const list3 = leadingThirtysevenList(list1);  //  Array [37, Array [1, 2, 3]]

function sum(arg1, arg2) {
    return arg1 + arg2
}

const result1 = sum(1, 2); // 3
const add = sum.bind(null, 37);
const result2 = add(5); // 42
const result3 = add(5, 10, 300); // 42 첫번째 인수를 제외한 나머지 인수는 무시

이상 this를 복습해봤습니다... 앗뇽,,,🙋🏻‍♀️

좋은 웹페이지 즐겨찾기