ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [멋쟁이사자처럼] 프론트엔드 스쿨 7기 - 29일차 기록 및 복습
    Front-end 개발 2023. 8. 16. 08:35

    목차

    1. JavaScript 전개구문

    2. JavaScript 디스트럭쳐링

    3. JavaScript this 키워드

    4. 함수 심화 

    5. 스코프

    6. 잡답


    1.  JavaScript 전개구문


    1-1. 전개구문

    - spread syntax

    - Spread 문법은 배열이나 객체와 같은 데이터 구조를 확장할 때 사용하는 문법

     

    1-2. 배열의 전개구문

    - 배열의 전개 구문은 대괄호([]) 안에서 세 개의 점(...)을 사용하여 배열을 확장한다.

    - 전개구문을 활용하여 배열의 값만을 복사해 새로운 배열을 만들 수도 있다.

    - 이렇게 생성된 배열은 기존의 객체 자료형처럼 참조를 공유하지 않고 완전히 별개인 새로운 값이 할당된다.

     

    1-3. 객체의 전개구문

    - 객체의 전개 구문은 중괄호({}) 안에서 세 개의 점(...)을 사용하여 배열을 확장한다.

    - 전개되는 객체들 중에 같은 이름의 key가 있다면, key 의 값은 나중에 온 객체의 키값으로 업데이트 할 수 있다.

    const me = { name: "철수", address: "서울" };
    const newAddress = {address : "서귀포시"};
    const newMe = {...me, name: "길수", ...newAddress};
    
    console.log(newMe); // {name: '길수', address: '서귀포시'}

    2. JavaScript 디스트럭쳐링


    2-1. Destructuring (구조분해할당)

    - destructuring MDN 번역문을 보면 '구조 분해 할당'으로 나온다. 뜻은 네이버 기준으로 '...의 구조를 파괴[해체]하다'

    - 디스트럭쳐링은 ES6 부터 지원하는 문법으로, 배열이나 객체아 같은 데이터 구조를 분해하여 변수에 할당하는 표현식

    - 더 간결하고 빠르게 작성할 수 있는 구문으로 사용된다.

     

    2-2. 객체의 디스트럭쳐링

    - 디스트럭쳐링의 기본 구조

    let obj = {one: 1, two : 2};
    let myNum = obj.one;
    console.log(myNum);
    
    let obj = {one: 1, two : 2};
    let {one: myNum} = obj;
    console.log(myNum);

    - 생김새가 정확히 객체 리터럴과 동일하나, 왼쪽에 있으면 디스트럭쳐링이고 오른쪽에 있으면 객체 리터럴이다.

    - 위 예제에서 디스트럭쳐링의 {one: myNum} 은 myNum 이 데이터의 이름을, one 이 데이터의 값을 나타냄

    // 왼쪽이 디스트럭처링, 오른쪽이 객체 리터럴이다.
    let {one:myNum} = {one:1};
    console.log(myNum); // 1

    - 디스트럭쳐링은 이름과 콜론을 생략할 수 있다.

    /*
    let food1, food2, food3;
    const categories = {food1 : '과일', food2 : '채소', food3 : '육류'};
    
    food1 = categories.food1;
    food2 = categories.food2;
    food3 = categories.food3;
    */ 
    const { food1, food2, food3 } = { food1: '과일', food2: '채소', food3: '육류' };
    
    console.log(food1, food2, food3);

    - 실무에서도 그리고 react 에서도 많이 사용한다.

    - 디스트럭쳐링을 이용하면 반복과 불필요한 변수 생성을 줄여 코드를 깔끔하게 작성할 수 있다.

     

    2-3. 배열의 디스트럭쳐링

    - 배열의 경우는 객체의 디스트럭처링과 다르게 변수의 이름이 달라도 순서대로 들어간다.

    const arr = [1, 2, 3];
    
    const [a, b, c] = arr;
    
    console.log(a); // 1
    console.log(b); // 2
    console.log(c); // 3

     

    2-4. 함수의 디스트럭쳐링

    - 함수의 디스트럭쳐링은 함수의 매개변수를 분해해서 변수에 할당하는 방법

    - 객체로 받는 것도 가능함

    // 함수에서 배열의 스트트럭쳐링
    function myFunc([a, b]) {
      console.log(a); 
      console.log(b);
    }
    
    const arr = [1, 2];
    myFunc(arr);
    
    // 함수에서 객체의 스트트럭쳐링
    function myFunc({a, b}) {
      console.log(a); 
      console.log(b);
    }
    const obj = {a:1, b:2};
    myFunc(obj);

    3. JavaScript this 키워드


    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

     

    this - JavaScript | MDN

    JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 또한 엄격 모드와 비엄격 모드에서도 일부 차이가 있습니다.

    developer.mozilla.org

     

    3-1.  this 키워드

    - mdn 설명은 생각보다 불친절하다.

    - this는 객체를 가리키는 참조 변수이다. this는 호출 위치에 따라 다른 값을 출력하기 때문에 우리에게 혼란을 준다.

    - 보통은 함수 안에서 사용된다.

    function a() {
        console.log(this);
    }
    a(); // window 객체
    
    const myObj = {
        val1: 100,
        func1() {
            console.log(this);
        }
    }
    
    myObj.func1();

    - Window 객체: 브라우저 환경의 전역 공간을 의미한다. Node.js 환경에서의 전역공간은 global 이란 이름을 가진다.

    - window 는 생략이 가능하며, 함수 a()를 선언하면 window 객체에 생성되어 window.a() 와 같이 정의된다.

    - 어떤 객체의 메소드가 아닌 단독 호출되는 함수의 this 는 전역공간을 참조하게 된다.

    let myObj = {
        val1: 100,
        func1: function () {
            console.log(this);
        }
    }
    
    let test = myObj.func1;
    test() // Window 객체

    - 기본적으로 this 는 함수를 호출하는 객체를 가르킴

    - this가 가리키는 개체는? this 키워드를 가지고 이는 함수를 호출하는 개체

    - 전역공간에서 호출하게되면 가리키는 것은 window 객체이다.

    - 그렇기 때문에 전역공간에서 선언한 변수(var) 를 참조할 수 있다.

    - let, const 는 전역 공간에 선언되지 않는다.

    function sayName() {
        console.log(this.name);
    }
    
    var name = 'Hero';
    let name2 = 'here';
    const name3 = 'here';
    // 전역으로 선언한 name 변수의 앞에는 window 가 생략되어 있습니다. 
    // 때문에 window.name === "Hero" 가 성립합니다.
    let peter = {
        name: 'Peter Parker',
        sayName: sayName
    }
    
    let bruce = {
        name: 'Bruce Wayne',
        sayName: sayName
    }
    
    sayName();
    peter.sayName();
    bruce.sayName();

    - 참고로, name 은 기본적으로 window 객체에 있는 속성이다.

    - 전역공간에서 this 는 전역공간을 가리킨다.

    - 함수 안에서의 this는 this 를 가지고 있는 함수를 호출하는 객체를 가리킨다.

    - this 는 함수가 만들어질 때가 아닌 '실행'될 때 그 값이 결정된다.

    - 다이나믹 스코핑 : 실행되야 알 수 있는 것

    - Lexical 스코핑 : 문법적으로 알 수 있는 것

     

    3-2. this 값을 사용자의 의도대로 조작하기

    - apply(), call(), bind()

    - call() 은 콤마를 통해서 인자를 전달해줄 수 있다.

     

    3-3. call()

    var peter = {
      name : 'Peter Parker',
      sayName : function(){    
    		console.log(this.name);
    	}
    }
    
    var bruce = {
      name : 'Bruce Wayne',
    }
    peter.sayName.call(bruce); // Bruce Wayne

    - 아규먼트를 전달해줄 수 있다.

    var peter = {
      name : 'Peter Parker',
      sayName : function(감탄사){    
    		console.log(this.name + 감탄사);
    	}
    }
    
    var bruce = {
      name : 'Bruce Wayne',
    }
    peter.sayName.call(bruce, '!'); // Bruce Wayne!

     

    3-4. apply()

    - call() 과 유일한 차이는 단일한 배열로 전달하는 아규먼트의 차이

    - 배열 내부의 순서대로 아규먼트로 전달된다.

    var peter = {
      name : 'Peter Parker',
      sayName : function(is, is2){    
    		console.log(this.name+ ' is '+ is + ' or ' + is2);
    	}
    }
    
    var bruce = {
      name : 'Bruce Wayne',
    }
    
    peter.sayName.apply(bruce, ['batman', 'richman']); // Bruce Wayne is batman or richman
    
    /* peter.sayName.apply(bruce, ['batman', 'richman']) 의 결과가 무엇이 될지 생각해보고 
    apply 를 call로 바꾸어 호출했을 때와 비교해 봅시다. */

     

    3-5. bind()

    - this가 고정된 새로운 함수를 반환한다.

    function sayName(){
      console.log(this.name);
    }
    
    var bruce = {
      name: 'bruce',
      sayName : sayName
    }
    
    var peter = {
      name : 'peter',
      sayName : sayName.bind(bruce)
    }
    
    peter.sayName(); // bruce
    bruce.sayName(); // bruce
    
    /* peter.sayName() 과 bruce.sayName() 의 결과 값이 무엇이 될지 생각해봅시다. */

    - this에 바인딩되는 객체가 동적으로 결정되는 기명함수와 달리 화살표 함수의 경우 상위 스코프의 this 를 가리킵니다. 이러한 방식을 (정의된 코드를 보고 알수 있는) 렉시컬(Lexical) 스코프 라고 부릅니다.

    const person = {
        name: 'hojun',
        age: 25,
        a() {
            console.log(this); // person
            console.log(this.name); // hojun
            function b() {
                console.log(this); // window
                console.log(this.name); // '' window (기존 window 의 name 은 빈문자열)
                function c() {
                    console.log(this); // window
                    console.log(this.name); // '' window (기존 window 의 name 은 빈문자열)
                }
                c();
            }
            b();
        }
    }
    person.a()

    - 메소드로써 실행되는 함수는, 객체에 들어가있는 함수이기 때문에 객체를 가리킨다.

    - a() 는 person 의 매소드다.

    - b()와 c() 는 단독 호출되어 실행되는 함수는 window 객체를 가리킨다.

    - a() 를 전역으로 선언하여 사용하면 전역공간에서 실행됬으며, 단독 호출되어 이것 또한 window 객체를 가리킨다.

    const func = person.a;
    func(); // window

     

    3-6. 화살표함수에서 this

    - 화살표함수에서는 this 를 감싸고 있는 함수의 상위 스코프의 객체를 가리킨다.

    // a에서 this = person
    // b에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person
    // c에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person
    const person = {
        name: 'hojun',
        age: 25,
        a(){
            console.log(this); // {name: 'hojun', age: 25, a: ƒ} 
            console.log(this.name); // hojun
            let b = () => {
                console.log(this); // {name: 'hojun', age: 25, a: ƒ} 
                console.log(this.name); // hojun
                let c = () => {
                    console.log(this); // {name: 'hojun', age: 25, a: ƒ} 
                    console.log(this.name); // hojun
                }
                c()
            }
            b()
        }
    }
    person.a()

    - 화살표 함수를 피해야하는 경우 (this 가 전역을 가리키는 경우)

    let 인세규정 = {
        책:10,
        영상콘텐츠:50
    };
        
    [100, 200, 300].map(e => e *(this.책/100), 인세규정); // [NaN, NaN, NaN]
    [100, 200, 300].map(e => this, 인세규정); // [Window, Window, Window]

     

    3-7. forEach 문에서 this 

    - forEach 두번째인자로 this 의 인자로 사용할 수 있다.

    - 두번째 인자를 빼면 전역에서 실행되기 때문에 window 를 가리킴

    [1, 2, 3].forEach(function(){console.log(this)}, [10, 20, 30])
    // [10, 20, 30]
    // [10, 20, 30]
    // [10, 20, 30]

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

     

    Array.prototype.forEach() - JavaScript | MDN

    forEach() 메서드는 주어진 함수를 배열 요소 각각에 대해 실행합니다.

    developer.mozilla.org

     

    3-8. map 에서 this

    - 두번째인자로 thisArgs 를 줄 수 있다.

    let 인세규정 = {
        책:10,
        영상콘텐츠:50
    };
    
    function 인세계산함수(e){
        return e *(this.책/100)
    };
        
    [100, 200, 300].map(인세계산함수, 인세규정); // [10, 20, 30]

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map

     

    Array.prototype.map() - JavaScript | MDN

    map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

    developer.mozilla.org

     

    3-9. 정리

    - 메서드로 호출할 경우 this 는 멤버접근연산자 앞의 객체를 가리킨다. (예시: obj.foo())

    - 함수로 호출한 경우 this 는 window(node는 global) 를 가리킨다.

    - 화살표 함수의 경우 this 는 상위 스코프를 가리킨다.

    - 생성자 함수 혹은 class 의 경우 this 는 인스턴스를 가리킨다.

     

    4. 함수 심화


    4-1. 구조분해할당을 이용한 아큐먼트 처리

    - 매개변수에 디스트럭쳐링을 사용하려고 한다면, 매개변수에 빈 객체라도 할당을 해주어 초기화하여 예외처리를 한다.
      (코딩 버릇을 가지자, 방탄코딩)

    - 디스트럭쳐링을 함수의 매개면수(파라미터)에서 이루어지고 있다. 
      {name, age, email} = { name: '재현', age: 25, email: 'jaehyun@something.com' }

    function printMe({ name, age, email } = {}) {
      console.log(`이름: ${name}, 나이: ${age}, 이메일: ${email}`);
    }
    
    const me = {
      name: '재현',
      age: 25,
      email: 'jaehyun@something.com'
    };
    
    printMe(me);

     

    4-2. rest 문법

    - 함수의 매개변수에 ...를 붙이면 사용자가 제공한 모든 매개변수를 배열안에 넣도록 지정

    - rest 문법을 사용할 때 주의할 점

     (1) 매개변수에는 하나의 rest 만 존재할 수 있다.

     (2) rest 는 반드시 함수 정의의 마지막 매개변수여야 한다.

    function 함수2(a, b, ...c){
        console.log(c)
        return Math.max(...c)
    }
    
    함수2('hello', 'world', 10, 20, 30, 40)
    // [10,20,30,40]
    // 40
    
    function 함수2([a, b], ...c){
        console.log(a)
        console.log(b)
        console.log(c)
    }
    
    함수2([1, 2], 10, 20, 30, 40)
    // 1
    // 2
    // [10, 20, 30, 40]

    - 사용하는 위치에 따라 spread 와 rest 로 나뉜다.

    - 함수의 마지막 매개변수에 사용되는 ...은 rest 문법으로 인식하고

    - 자바스크립트 엔진은 일반적인 객체나 배열안에서 사용되는 ...은 spread 문법으로 인식한다.

     

    4-3. 매개변수 초기화

    - 함수의 매개변수는 선언과 동시에 파라미터 값을 할당하여 초기화도 가능하다.

    - 매개변수의 초기화는 기본적으로 왼쪽에서 오른쪽으로 순서로 설정된다.

    - 매개변수 초기화는 함수 선언에서 일어나지 아규먼트에서 일어나지 않는다. (아큐먼트의 초기화식은 무시하자)

    function 함수3(a=10, b=20, c=30){
        return a + b + c
    }
    
    console.log(함수3())
    console.log(함수3(100))
    console.log(함수3(100, 200))
    console.log(함수3(100, 200, 300))
    
    console.log(함수3(c=1000)) // 1030이 되어야 하는거 아니에요? 
    // 1050
    
    console.log(함수3(c=1000, a=2000)) // 3020이 되어야 하는거 아니에요?
    // 3030
    
    // 값이 순서대로 들어갔습니다.

     

    5. 스코프 scope


    5-1. 스코프

    -스코프란 변수의 접근성과 생존 기간을 제어하는 '생존 범위'를 의미한다.

    const func1 = function(){
      var a = 1;
    	var b = 2;
      
      console.log(a + b);
    };
    
    var a = 20;
    
    func1(); // 3

    - 변수 a는 어디서든 접근 가능한 전역 변수임에도 불구하고 함수안밖의 a는 완전히 별개의 변수임을 알 수 있다.

    - 함수안 a변수는 함수가 종료면 함수 스코프가 가비지 컬랙션으로 수거되기 때문에, 메모리상에서 자동으로 제거된다.

    - 이렇듯 스코프는 이름이 충돌하는 문제를 덜어주고, 자동으로 메모리를 관리한다.

     

    5-2. 스코프의 종류

    (1) 전역 스코프 : 스크립트 어디서든 접근이 가능. 타인과 협업, 라이브러리 사용시 충돌의 가능성이 있다.

    (2) 함수 스코프 : 함수 내부에서 정의된 변수와 매개변수는 함수 외부에서 접근할 수 없다.

    (3) 블록 스코프 (ES6) : 중괄호 안에서만 접근 가능. 블록 내부에서 정의된 변수는 블록의 실행이 끝나면 해제됨

    - 스코프 체이닝: 현재 스코프에서 찾을 수 없는 값을 찾기 위해 스코프를 이동하는 것

    - 함수 스코프는 var 를 포함하여 절대 외부에서 내부로 접근이 불가능하다. (내부에서 외부 접근은 가능하다)

    let z = 100;
    function sum(x){ // x는 매개변수(parameter)이면서 지역변수(local val)
      let y = 50; // y는 지역변수
      z = z + y;
      return x + y;
    }
    console.log(sum(10)); // 10은 전달인자(argument)
    console.log(x); // 오류
    console.log(y); // 오류
    console.log(z); // 150
    
    // 블록 레벨 스코프
    if(true){ // for문이어도 마찬가지입니다.
        let k = 10;
        const t = 10;
    }
    console.log(k, t) // 오류
    
    for(var i=0; i<10; i++) {}
    console.log(i); // 10
    
    
    // scope chaining
    let a = 10;
    
    function outer() {
        let b = 20;
    
        function inner() {
            let c = 30;
            console.log(a, b, c);
        }
    
        inner();
        console.log(a, b);
    }
    
    outer();
    // 10 20 30
    // 10 20

     

    6. 잡담 시간


    6-1. 신입으로 들어간 회사

    - 처음 들어보면 선임의 코드를 분석하는 일을 시킨다.

    - 회사에서 무지를 드러내지 않기 위해 숨기는 건 회사에서도 문제다.

    - 질문을 많이 해라

    - 어떻게 질문을 해야 욕을 먹지 않을까?

      > 자기가 이해한 바를 이야기하고, 어떤 노력을 해봤는데, 이해가 안된다고 해야 한다.

      > 충분한 고민을 해보고 질문한다는 걸 보여줘야 한다.

    - 너무 고민하는 것은 마이너스다

      > 업무에 지장이 가는 고민을 하면 안된다. (고민은 1시간 내로 해야 함)

      > 계속 후벼파면서 다른 모르는 걸 찾다가 일을 못한다.

      > 이러면 정해진 기간이 길어지면 선임이 왔을 때 진척은 없고 속상하다.

     

Designed by Tistory.