ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] 그래서 this가 뭔데?
    문제와 해결/Javascript 2021. 5. 2. 22:04

    아무 창에서나 개발자 모드를 키고 다짜고짜 this를 찍어보자.

    이때 this의 output은 window로 출력된다. 

     

    이번에는 object 안에서 this를 사용해보자.

    fullName은 함수이고, fullName이라는 함수 안에서 this가 쓰이고 있으므로 우리는 이 함수를 호출하고 결과를 확인해보자. 함수가 실행된 결과를 봐야 하므로 person.fullName이 아니라 person.fullName()으로 입력하는걸 잊지 말자.

    이때 출력 결과를 보면 thisthis가 속해있는 object를 지칭한다는 걸 알 수 있다.

     

    this가 어디에서 쓰이는지에 따라 this가 무엇인지는 조금씩 다른데, 이건 w3schools에 친절하게 나와있는 설명을 한번 보도록 하자.

     

    this란?

    • method 에서 : this 는 method를 소유한 object를 지칭한다.
    • 단독으로: this는 global object를 지칭한다.
    • function에서 : this는 기본적으로는 global object, function의 owner를 지칭한다. 
    • strict mode의 function에서: this는 undefined 값을 가진다.
    • event에서: this는 해당 event가 실행될 element를 지칭한다.
    • call(), apply()같은 method에서: this는 아무 object나 다 될 수 있다.  

    친절한 설명이지만 확 와닿지는 않는다. this가 무엇인지는 일단 설명되었지만, 그럼 global object는 뭔데? method랑 function이 다르다고? 같은거 아니었어? strict mode의 functions은 또 뭔데? call() 이나 apply()는 왜 또 다른 method랑 다른데?

     

    당황하지 말고 차근차근 의문점을 해결해 나가자.

     

    method와 function의 차이는 뭘까?

    사실 method와 function의 차이에 대해서는 여러 논란들이 있다. 다만 여기서 우리는 w3school에서 설명한 this를 이해하고자 하므로 간단하게, '흔히 알려진 차이'에 대해서만 알아보자. 

     

    method는 이미 우리가 위에서 한번 쓴 적이 있다. object의 property가 function으로 정의된 경우, 우리는 그걸 method라고 부른다. 따라서 method와 function은 전혀 별개의 것을 지칭하는게 아니다. function은 method를 포함하는 개념이다. 사실 더 알아야 하는 부분도 있지만 일단 여기서는 그렇게 알고 넘어가자.

    method는 다음과 같은 양식을 가지며, 우리가 위에서 썼던 person.fullname()도 method이다. 

    object = {
    	methodName: function(){
        	//content
        }
    }

     

     

    function은 어떠한 일을 수행하기 위해 쓰인 코드로, 흔히 우리가 함수라고 하면 떠올리는 것을 말한다.

    function functionName(parameters){
    	//content
    }

     

    그럼 이제 global object가 무엇인지 알아보자.

     

    Global Object란?

    전역 객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미하며, 일반적으로 Brower-side에서는 window, Server-side(Node.js의 경우) global 객체를 의미한다.

     

    window가 여기서 나온다고? 우리는 아까 개발자 도구에서 this의 출력결과가 window인 것을 확인했고, this가 무엇인지 알아보며 단독으로 쓰인 this는 global object를 지칭한다는 것 역시 확인했다. Global Object는 window라는 것으로 아주 많은 의문들이 해소된다... 다만 this를 더 똑똑하게 쓰기 위해, 여기서 멈추지 말고 Global Object에 대해서 조금 더 알아보자.

    • 개발자는 전역 객체를 생성할 수 없다. (실행 컨텍스트에 컨트롤이 들어가기 이전에 생성되며, construnctor이 없어 new 연산자를 이용해서 새롭게 생성할 수 없기 때문)
    • 전역 객체는 Global Scope를 가진다. (웹 페이지의 모든 함수와 scripts가 접근하여 사용할 수 있다.)
    • 전역 객체의 자식 객체를 사용할 때 전역 객체를 생략하여 사용할 수 있다.
      ex) document는 전역 객체의 자식 객체로, window.document....와 같이 사용하는 대신 보통 document....와 같이 쓰인다.
    • 만약 사용자가 정의한 변수와 전역 객체의 자식 객체 이름이 충돌하는 경우, 전역 객체를 기술하여 혼동을 방지할 수 있다.

    해당 코드를 개발자 도구에서 실행하면, alert로 "move to http://www.google.com"이 뜨고, 브라우저는 http://www.google.com 주소의 웹페이지로 이동한다.

    • 전역 변수와 함수는 전역 객체의 property이다.

    • standard built-in object(ex. alert()) 도 전역 객체의 자식 객체이다.

    얼추 global object에 대해 알아보았지만...strict mode에 대해 알아보기 전에, this를 더 잘 이해하기 위해서는 binding에 대해 이해할 필요가 있다.

     

    binding이란?

    우리는 위에서 this가 대부분의 경우에 전역 객체, 그러니까 window를 가리킨다는 것을 배웠다. 하지만 함수 안에서 this를 사용하되, 이 this를 window가 아닌 다른 객체로 바꾸고 싶을 수 있다. 이것을 바인딩이라고 한다.

    물론, 왜 그런 짓을 하지? 라고 생각할 수 있다. 그러니까 예시와 함께 살펴보자.

     

    우리에게 다음과 같은 함수가 있다.

    function hello(){
    	console.log(this);
    	console.log("Hello, my name is " + this.name);
    }
    hello();

    hello 함수를 개발자 도구에서 실행시켜 보자.

    당연히 this는 window를 가리키고, 두번째 console.log 에서 this.name은 현재 존재하지 않는 파라미터이므로 완성되지 않은 문장 "Hello, my name is "만이 출력된다.

    이때, this가 전역객체가 아닌 다른 객체를 가리키도록 하면 우리는 완성된 이름을 출력시킬 수 있을 뿐만 아니라 그때그때 다른 이름으로, 다른 인삿말을 출력시킬 수 있을 것이다.

     

    그럼 어떻게 바인딩을 할 수 있을까? 바인딩을 가능하게 하는 함수로는 call(), apply(), bind()가 있다. 앗 왠지 익숙한데...라고 생각했다면, 맞다! 위에서 this가 무엇인지 살펴보았을 때, call이나 apply와 같은 함수에서는 this가 아무 객체나 다 될 수 있다는 내용이 있었다. 이제 그에 대해 더 자세히 알아보자.

     

    call() , apply(), bind()

    call과 apply는 javascript에서 기본적으로 정의되어있어서 언제나 마음대로 쓸 수 있는 함수이다. 둘 다 object method를, 또 다른 object를 argument로 해서 호출하는데 쓰일 수 있다.

     

    사실 javascript에서 모든 function은 object의 method이다.

    뭐라고...?

    만약 function이 javascript object의 method가 아니라면, global object의 method이다.

    뭐라고....?

    당황하지 말고 위에서 공부했던 내용을 다시 생각해보자. 전역 객체에 대해 살펴봤을 때, 우리는 전역 변수와 전역 함수는 전역 객체의 property라는 내용을 확인한 바 있다. 전역 객체도 결국에는 object이므로 그것의 property인 전역 함수는...역시 method인 것이다!

    이것을 이해한 우리는 call이 어떤 방식으로 동작하는지도 이해할 수 있다.

     

    call()

    var person = {
      fullName: function() {
        return this.firstName + " " + this.lastName;
      }
    }
    var person1 = {
      firstName:"John",
      lastName: "Doe"
    }
    var person2 = {
      firstName:"Mary",
      lastName: "Doe"
    }
    person.fullName.call(person1);
    person.fullName.call(person2);

    개발자 도구에서 위의 코드를 실행시켜봐도 좋지만, 사실 실행시켜보지 않아도 대충 어떻게 동작할지 짐작이 갈 것이다. person.fullName.call(person1)는 "John Doe"를 출력하고, person.fullName.call(person2)는 "Mary Doe"를 출력한다.

     

    apply()

    var person = {
      fullName: function() {
        return this.firstName + " " + this.lastName;
      }
    }
    var person1 = {
      firstName: "Mary",
      lastName: "Doe"
    }
    person.fullName.apply(person1);  // Will return "Mary Doe"

     

    apply는 call과 같은 방식으로 사용된다. 결과 역시 같다. 그럼 왜 이름이 다를까?

    object외의 arguments를 주는 방식이 다르다.

    person.fullName.apply(person1, ["Oslo", "Norway"]);
    person.fullName.call(person1, "Oslo", "Norway");
    //둘 다 "John Doe,Oslo,Norway"를 반환한다

     

    bind()

    bind는 어떤 상황에 사용할까? call, apply와 달리 함수를 실행하지 않고 대신 bound 함수를 리턴하기 때문에 this를 binding만 하고 싶을 때 사용된다. 여태까지처럼 간단한 함수라면 bind가 필요하지 않을 수 있지만, 프로젝트를 하고 더 복잡한 코드를 짜게 되면 bind가 필요해진다.

    var newName = { name: "John Doe" }
    
    function hello(){
    	console.log(this);
    	console.log("Hello, my name is " + this.name);
    }
    
    const bindHello = hello.bind(newName);
    
    bindHello();
    console.log(bindHello);
    

    this는 newName 객체를 가리키고, 두번째 console log는 완성된 문장을 출력한다.
    bindHello는 bound 함수이다.

     

    strict mode는 연습단계에서는 잘 쓰지 않기 때문에 여기까지만 이해해도 this를 어려움 없이 쓸 수 있을 것이다. 초보개발자라면...! 고단한 하루였다면 이쯤해서 어려운 코딩공부는 그만두고 마음이 따뜻해지는 고양이와 강아지 영상을 보러 가도 좋지만, 그렇지 않다면 간단하게 strict mode에 대해 알아보자. 나는 오늘 신생아처럼 낮잠을 잔 관계로 조금 더 써보도록 한다.

    Strict Mode

    strict mode는 script의 시작(이 경우 global scope를 가지므로 script의 모든 내용이 strict mode로 실행된다), 혹은 function의 시작에 "use strict";를 추가하는 것으로 사용할 수 있다. 흔히 사용하는 react의 경우 기본적으로 strict mode로 실행된다.

     

    "use strict"는 ECMAScript version5 부터 사용되었고 그 이전의 버전에서는 무시된다. strict mode에서는 정의되지 않은 변수를 사용할 수 없게 된다. 아래의 예시가 대표적이다.

    strict mode는 왜 사용해야 할까?

    strict mode는 javascript를 더 안전하게 쓸 수 있게 해준다. "bad syntax"를 에러로 인식하기 때문에 코드를 더 엄밀하게 쓸 수 있게 되는 것이다. 

     

    strict mode또한 가볍게 다룰 내용은 아니지만, 이 포스팅에서는 다소 사족이 되므로 더 자세한 내용은 www.w3schools.com/js/js_strict.asp에서 확인하도록 하자.

     

     

     

    출처:

    blueshw.github.io/2018/03/12/this/

     

    [javascript] this는 어렵지 않습니다.

    this 는 어렵지 않습니다. this 를 어렴풋이 알고는 있지만, 누가 물어봤을때 제대로 대답해 줄수 있도록 정리해보겠습니다. 많은 개발자들이 javascript 의 this 를 혼란스러워합니다. 사실 개념 자체

    blueshw.github.io

    www.w3schools.com/js/js_this.asp

     

    JavaScript this

    The JavaScript this Keyword Example var person = {   firstName: "John",   lastName : "Doe",   id       : 5566,   fullName : function() {     return this.firstName + " " + this.lastName;   } }; Try it Yourself » What is this? The JavaScrip

    www.w3schools.com

    www.geeksforgeeks.org/difference-between-methods-and-functions-in-javascript/

     

    Difference between Methods and Functions in JavaScript - GeeksforGeeks

    A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

    www.geeksforgeeks.org

    poiemaweb.com/js-global-object

     

    Global Object | PoiemaWeb

    전역 객체(Global Object)는 모든 객체의 유일한 최상위 객체를 의미하며 일반적으로 Browser-side에서는 window, Server-side(Node.js)에서는 global 객체를 의미한다.

    poiemaweb.com

    wooooooak.github.io/javascript/2018/12/08/call,apply,bind/

     

    binding의 개념과 call, apply, bind의 차이점 · 쾌락코딩

    binding의 개념과 call, apply, bind의 차이점 08 Dec 2018 | javascript basic this es6 binding이란? 프로젝트 경험이 거의 없었을 때는 this를 binding한다는 말 조차 이해가 가지 않았었다. javascript기본서에서 call, app

    wooooooak.github.io

     

    '문제와 해결 > Javascript' 카테고리의 다른 글

    [JavaScript] data-* 속성 사용하기  (0) 2021.05.05
Designed by Tistory.