ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 this
    frontend/javascript&web 2022. 2. 18. 10:16

    쉽게 이해하는 자바스크립트 this 

     

    this

    • 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가르키는 자기참조변수

     

    자바스크립트의 this는 자바를 비롯한 여타 언어들과는 상이하게 동작합니다. 이 개념을 잘 이해하신다면 우리가 특정 변수나 객체에 접근할 때 발생할 수 있는 문제에 대하여 사전에 방지할 수 있는 효과를 가지게 될 것입니다.

     

    this의 동작방식

     

    this 값은 호출방법에 의해 결정됩니다. 실행중에 할당으로 설정할 수 없고 호출할 때마다 다르게 동작합니다. 우리는 이러한 this의 값 결정 방식을 5가지로 분류 해볼 수 있습니다.

     

    1. 전역공간
    2. 함수 호출
    3. 메소드 호출
    4. 생성자 함수 호출
    5. apply / call / bind 호출

    함수와 메소드를 혼동하지 맙시다. 함수는 객체로 부터 독립적이지만, 메소드는 객체에 종속되어 있습니다. 함수는 메소드를 아우르는 포괄적인 용어지만 다른 말이니 헤깔리지 않도록 합시다.

     

    예시

     

    1. 전역공간

    //Browser
    console.log(this); // window
    //NodeJS
    console.log(this); // global

    전역공간에서 자바스크립트 this값은 Browser(ClientSide) NodeJS(ServerSIde)환경에서 다르게 동작합니다. 기본적으로 this는 전역객체에 바인딩되며 전역객체는 모든 객체의 유일한 최상위 객체를 의미합니다.

     

    2. 함수 호출

    비 엄격 모드

    function outer(){
    	console.log("outer의 this",this);//window
    	function inner(){
    		console.log("inner의 this",this);//window
    	}
    	inner();
    }
    outer();

    엄격 모드

    "use strict"
    function outer(){
    	console.log("outer의 this",this);//undefined
    	function inner(){
    		console.log("inner의 this",this);//undefined
    	}
    	inner();
    }
    outer();

    함수 호출 시에도 기본적인 동작은 전역에서와 동일합니다. 하지만 "use strict"를 사용하여 엄격모드에 들어가면 this는 window 객체를 가르키지 않습니다. 개발할 떄 window객체를 개발자도 모르게 건드려 발생하는 사이드 이펙트를 막기위해 적용되었다고 합니다.

     

    3. 메소드 호출

    var value = 10;
    var test = {
    	value : 100,
    	getValue:function() {
    		console.log(this.value); // 100
    		function findValue() {
    			console.log(this.value); // 10
    		}
    		findValue();
    	}
    }
    test.getValue();

    메소드 호출시에는 this는 메소드 호출의 주체가 됩니다. getValue의 주체인 test가 된다고 볼 수 있습니다. 하지만 그 내부의 findValue는 전역을 가르키는 것을 볼 수 있습니다. 이런 것을 해결하기 위해서는 아래와 같이 작업할 수 있습니다.

    var value = 10;
    var test = {
    	value : 100,
    	getValue:function() {
    		console.log(this.value); // 100
    		const findValue = () => {
    			console.log(this.value); // 100
    		}
    		findValue();
    	}
    }
    test.getValue();

    화살표 함수를 활용하면 다시 전역의 value값을 들고 올 수 있습니다.

    var value = 10;
    var test = {
    	value : 100,
    	getValue:function() {
        	const self = this;
    		console.log(this.value); // 100
    		function findValue() {
    			console.log(self.value); // 100
    		}
    		findValue();
    	}
    }
    test.getValue();

    다른 방법으로는 전역 this의 값을 할당받아 놓는 방법도 있습니다. 콜백과의 복합적인 상황에서도 재밋게 동작합니다.

    const person = {
    	name : null,
    	setName : function(name) {
    		this.name = name;
    	}
    };
    
    function setPersonName(name, callback) {
    	callback(name);
    }
    
    setPersonName("류호진",person.setName);
    
    console.log(person.name); // null
    console.log(window.name); // 류호진

    메소드를 콜백 함수로 사용하게 되면 메소드가 함수로써 호출되면서 객체와의 연결성이 사라져 this가 employee가 아닌 window를 바라보게 되면서 위와 같은 현상이 발생하게 됩니다.

     

    4. 생성자 함수 호출

    function Person(name, age){
    	this.name = name;
    	this.age = age;
    }
    
    let person1 = new Person("류호진", 100);
    
    console.log(person1)
    
    /**
    Person {
        name : '류호진',
        age : 100
    }
    */

    new 키워드를 통해 생성자 함수 호출을 하게 되면, this는 객체 자기자신을 가르키게 됩니다. 하지만 new 키워드 없이 함수를 호출하면 어떻게 될까요?

    function Person(name, age){
    	this.name = name;
    	this.age = age;
    }
    
    Person("류호진", 100);
    
    console.log(window)
    
    /**
    window {
        name : '류호진',
        age : 100
    }
    */

    아주 당연하게도 일반함수 처럼 전역에 올라가있는 것을 확인할 수 있습니다.

     

    5. call / apply / bind 호출

     

    마지막으로, call / apply / bind 에 대하여 알아 보겠습니다. 자바스크립트 함수는 일급 객체이기 떄문에 메소드를 사용할 수 있습니다. call, apply, bind 메소드를 사용해서 함수를 실행 시킬 수 있는데, 함수가 호출될 컨텍스트를 지정하여 함수를 호출할 수 있게 도와줍니다. 이를 통해 this키워드가 무엇을 참조할지 명시적으로 지정할 수 있는 명시적 바인딩을 할 수 있습니다.

    일급객체란 다른객체에 일반적으로 적용가능한 연산을 모두 지원하는 객체를 말하는 것으로, 변수에 할당할 수 있어야 하고, 다른 삼수를 인자로 전달받을 수 있으며, 다른함수의 결과로써 리턴될 수 있는 객체를 말합니다.

     

    call

    Func.call(thisArg[, arg1[, arg2[...]]])

    call은 함수를 즉시 호출하며 위와 같은 매개변수 구조를 가집니다

    • thisArg : Func 호출에 제공되는 this의 값을 명시
    • arg 1, 2... : Func이 호출되어야하는 인수
    let person = {
    	name : "호진"
    };
    
    let employee = {
    	name : "무개"
    	hire : function(position) {
    		console.log(`${position} 개발자 ${this.name}이 고용 되었습니다`);
    	}
    }
    
    employee.hire.call(person,'Front-End'); // Front-End 개발자 호진이 고용 되었습니다

    위의 코드를 보면 this의 값을 person으로 명시하였기 때문에 call을 이용하여 호출하면 호진이 고용되었다는 메소드를 보여주게 됩니다.

     

    apply

    Func.apply(thisArg,[argsArray])

    apply는 함수를 즉시 호출하며 위와 같은 매개변수 구조를 가집니다

    • thisArg : Func 호출에 제공되는 this의 값을 명시
    • [argsArray] : Func이 호출되어야 하는 인수를 지정하는 유사배열 객체
    let person = {
    	name : "호진"
    };
    
    let employee = {
    	name : "무개"
    	hire : function(position) {
    		console.log(`${position} 개발자 ${this.name}이 고용 되었습니다`);
    	}
    }
    
    employee.hire.apply(person,['Front-End']); // Front-End 개발자 호진이 고용 되었습니다

    apply와 call의 차이점은 첫번째 인자를 제외하고 필요한 파라미터를 apply는 배열로 집어 넣어야 한다는 것입니다. call은 필요한 인자를 넣을때 (thisArgs, "0번값","1번값") 넣는다면 apply는 (thisArgs,["0번값","1번값"]) 이렇게 넣으셔야 됩니다.

     

     

    bind

    Func.bind(thisArg[, arg1[, arg2[...]]])

    bind는 함수를 즉시 호출하지 않으며 원본 함수를 복제한 새로운 함수를 반환해주기만 합니다. 또한 반환된 함수를 실행해야지만 원본함수가 실행됩니다. 위와 같은 매개변수 구조를 가집니다

    • thisArg : Func 호출에 제공되는 this의 값을 명시
    • arg 1, 2... : Func이 호출되어야 하는 인수
    let person = {
    	name : "호진"
    };
    
    let employee = {
    	name : "무개"
    	hire : function(position) {
    		console.log(`${position} 개발자 ${this.name}이 고용 되었습니다`);
    	}
    }
    
    let company = employee.hire.bind(person,'Front-End');
    company(); // Front-End 개발자 호진이 고용 되었습니다

     

     

    추가로 알고가는 Arguments에 대하여..

     

    함수에 전달되는 인수에 해당하는 Array형태의 객체를 arguments객체를 통해서 받을 수 있습니다.

    function position(x, y, z) {
    	console.log(arguments);
    }
    position(1, 3, 2); // Arguments(3) [1, 3, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]

    이렇게 유사배열인 arguments객체를 통해서 받을 수 있습니다. 하지만 이것은 유사배열이지 배열이 아니기 때문에 배열의 메소드를 사용할 수 없습니다. 배열의 메소드를 사용하기 위해서는 call과 apply를 활용하여 사용할 수 있습니다.

    function position(x, y, z) {
    	console.log(Array.prototype.join.call(arguments));
    }
    position(1, 3, 2); // 1,3,2

     

    오늘은 자바스크립트 this의 개념에 대해서 전반적으로 보았습니다. 헤깔릴 수 있는 개념이고 기업들의 면접질문에도 단골질문으로 나오는 개념이니 꼭 알고가셨으면 좋겠습니다. 항상 최대한 쉽게 알려드릴 수 있도록 해보겠습니다.

    반응형

    댓글

Designed by Tistory.