ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 원시 값과 객체, 얕은vs깊은 복사, 함수(재귀, 콜백)
    Javascript/모던자바스크립트 Deep Dive 2022. 12. 31. 00:39

    p.137

    원시 값과 객체의 비교

    원시타입의 값은 변경 불가능한 값이다. (읽기전용 값으로 변경 불가능)

     

    변수는 언제든지 재할당을 통해 변수 값을 변경 할 수 있다.

    상수는 재할당이 금지된 변수를 말한다.

    상수도 값을 저장하기 위한 메모리 공간이 필요하므로 변수라고 할 수 있다.

    단, 변수는 언제든지 재할당을 통해 변수 값을 변경할 수 있지만 ex) var, let

    상수는 단 한번만 할당이 허용되므로 변수 값을 변경 할 수 없다. ex) const

     

    변수에 새로운 원시 값을 재할당하면 메모리 공간에 저장되어 있는 재할당 이전의 원시 값을 변경하는 것이 아니라 

    새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장한 후, 변수는 새롭게 재할당한 원시 값을 가리킨다.

    이때 변수가 참조하던 메모리 공간의 주소가 바뀐다.

    (변수가 참조하던 메모리 공간의 주소가 변경된 이유는 변수에 할당된 원시 값이 변경 불가능한 값이기 때문이다.)

     

    원시 값과 객체의 비교

    //문자열을 재할당 했을 때 새로운 메모리에 world를 만들고 해당 메모리주소를 가르킨다.
    var str = "Hello";
    str = "world"
    
    //문자열은 유사 배열 객체이면서 이터러블이므로 배열과 유사하게 각 문자에 접근할 수 있다.
    var name = "woony"
    console.log(name[0]) //w
    console.log(name.length) //5
    console.log(name.toUpperCase()) "WOONY"
    
    //그러나 문자열은 원시타입 값이므로 변경할 수 없다. 에러는 나지 않는다.
    name[0] = "J"; // 코드가 먹지 않는다.
    console.log(name); //woony

    값에 의한 전달

    var score = 90
    
    var copy = score
    
    🔥중요🔥
    //score의 값(90)을 복사하여 copy라는 변수를 새로운 메모리에 저장한다.
    //즉 score 변수와 copy변수의 값80은 다른 메모리 공간에 저장된 별개의 값이라는 것에 주의
    //따라서 score의 값을 변경해도 copy변수의 값에는 어떠한 영향을 주지 않는다.
    
    console.log(score === copy) // true
    score = 100;
    console.log(score,copy) // 100 80
    console.log(score === copy) // false

    엄격하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달되기 때문이다.

    이는 밴수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있기 때문이다.

    결국은 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어

    어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다는 것이다.

     

    객체타입의 값, 즉 객체는 변경 가능한 값이다.

    원시 값을 할당한 변수를 참조하면 메모리에 저장되어 있는 원시 값에 접근한다.

    하지만 객체를 할당한 변수를 참조하면 메모리에 저장되어 있는 참조 값을 통해 실제 객체에 접근한다.

     

     

    p.150

    얕은 복사(Shallow copy) 와 깊은 복사(deep copy)

    객체를 프로퍼티 값으로 갖는 객체의 경우 얕은 복사는 한 단계까지만 복사하는 것을 말하고

    깊은 복사는 객체에 중첩되어 있는 객체까지 모두 복사하는 것을 말한다.

    const obj = { x : { y : 1 } };
    
    //obj의 x값까지만 복사하게 되며 이는 얕은복사라고 한다.
    const copy = { ...obj }
    
    //얕은복사를 했기 때문에 { y : 1 } 은 obj와 copy모두 같은 메모리를 참조한다.

    p.154

    함수

    함수는 코드의 재사용 측면에서 매우 유용하다.

    유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.

    함수는 객체 타입의 값이다.

    //함수 선언문
    fuction add(x,y){
    	return x+y
    }
    
    //함수 표현식
    var add = function (x,y) {
    	return x+y
    }
    
    //Function 생성자 함수 
    var add = new Function('x','y','return x+y')
    
    //화살표함수(ES6)
    var add = (x,y) => x+y

    기명 함수 표현식

    let Hello = function(who){
      if(who){
        alert(`Hello ${who}`);
      }else{
        Hello('Guest'); //Hello = null;을 하게 되면 오류가 나는 위치
      }
    }
    
    const welcome = Hello;
    welcome('woo'); // 결과는 Hello woo
    
    //그러나 아래처럼 Hello 에 null을 넣게 되면 Hello 함수 안에 Hello('Guest')를 호출하고 있는데 
    //Hello를 null로 바꿔버려서 오류가 나는 것이다.
    Hello = null;
    welcome(); // error!

    기명 함수 표현식을 사용하면 외부 변수 변경과 같은것들을 고려하지 않아도 되기 때문에,

    충분히 기억해 둬야 할 문법이다.

    //따라서 다음과 같이 기명 함수 표현식을 이용한다.
    let Hello = function guestHi(who){
      if(who){
        alert(`Hello ${who}`);
      }else{
        guestHi('Guest'); //Hello = null;을 하게 되면 오류가 나는 위치
      }
    }

    👍 참고: 기명 함수 표현식은 말 그대로 함수 표현식 에서만 사용할 수 있다. 함수 선언문에서는 사용 불가능.

     

    p.164

    함수 생성 시점과 함수 호이스팅

    함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르다.

     

    🌈중요 = 함수선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성되며

    함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체를 할당한다.

    런타임 이전에 함수객체가 먼저 생성되어 함수 선언문 이전에 함수를 참조할 수 있으며 호출도 가능하다.

    이를 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징 => 함수 호이스팅이라 한다.

     

    그러나 함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.

    (var 키워드로 선언된 변수는 undefined로 초기화되고

    변수 할당문의 값은 할당문이 실행되는 시점, 런타임에 함수 객체가 되어 할당된다.)

    console.log(add) // f add(x,y)
    console.log(sub) // undefined
    
    console.log(add(2,5)) // 7
    console.log(sub(2,5)) // TypeError:sub is not a function
    
    
    //함수 선언문
    function add(x,y){
    	return x+y
    }
    //함수 표현식
    var sub = fuction(x,y){
    	return x-y
    }

    함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야 한다는 당연한 규칙을 무시한다.

    이로인해 JSON 창시자인 더글라스 크락포드는 함수선언문 대신 함수 표현식을 사용할 것을 권장한다.

     

    재귀함수 : 함수 안에서 자기 자신을 호출하는 함수

    const factoial = function foo(n) {
    //탈출조건 : n이 1 이하일 때 재구 호출을 멈춘다.
    if ( n <= 1 ) return 1;
    return n * factorial(n-1);
    };
    
    console.log(factorial(5)); // 5*4*3*2*1 =120
    
    //윗 예제처럼 반복문 없이 반복을 처리 할 수 있다는 장점이 있다.
    //그러나 이해의 어려움이 있어 재귀 함수가 더 직관적일 때만 재귀함수를 사용한다.

    고차함수 : 함수를 인자로 받거나 결과로 반환하는 함수

    콜백함수 : 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수

    //다음은 callback함수의 예시이다.
    
    function repeat(n,fun){
    	for(var i=0; i<n; i++){
        fun(i) 
        //repeat 함수가 실행될 때 병경되는 일을 함수 f로 추상화 했고 
        //해당 함수를 외부에서 전달 받는다.)
    }
    
    const logAll = (n) => {
    	console.log(n)
    }    
    
    repeat(5, logAll); // 0 1 2 3 4
    
    const logOdds = (n) => {
    	if(n%2) console.log(n)
    };
    
    repeat(5, logOdds); // 1 3
    
    🌈정리
    repeat함수는 고차함수이다.
    fun은 repeat 함수의 콜백함수이다. (logAll이나 logOdds가 인수로 전달되면 콜백함수가 된다)

    순수함수와 비순수함수

    순수함수 : 외부의 상태를 변경하지 않는 함수

    //순수 함수 예시
    var count = 0;
    var increase = (n) => {
    	return ++n
    }
    
    count = increase(count);
    console.log(count) // 1
    
    count = increase(count);
    console.log(count) // 2

    비순수 함수 : 외부의 상태에 의존하는 함수 : 권장하는 방식이 아니다.

    //비순수 함수의 예시이다.
    //count의 값을 함수에서 직접적으로 변경하고 있다.
    var count = 0;
    var increase = () => {
    	 return ++count
    }
    
    increase(); 
    console.log(count); //1
    increase(); 
    console.log(count); //2

    ✨ 함수를 공부하며 궁금했던 점 :

    자바스크립트 함수는 일급 객체이다.

    이처럼 값의 성질을 갖는 객체를 일급객체라고 한다.

    자바스크립트의 함수는 일급객체이다.

     

    일급객체와 관련된 자세한 내용은 해당 블로그에 잘 정리되어 있기에 참고하기로 했다!

    https://velog.io/@reveloper-1311/%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4First-Class-Object%EB%9E%80

     

    일급 객체(First Class Object)란?

    자바스크립트를 공부하다보면 라는 말을 한 번쯤은 들어보았을 것이다. 이번에는 그 가 무엇인지에 대해서 정리해보고자 한다. 일급 객체(1급객체, First Class Object) 일급객체에 대한 정의이다. >

    velog.io

     

    댓글

Designed by Tistory.