ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데이터 타입
    카테고리 없음 2023. 4. 6. 23:32

    1. 복제의 방식
      1. 기본형 : 값이 담긴 주소값을 바로 복제
      2. 참조형 : 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
    2. 불변성의 여부
      1. 기본형 : 불변성을 띔
      2. 참조형 : 불변성을 띄지 않음

    메모리, 데이터

    1. 비트
      1. 컴퓨터가 이해할 수 있는 가장 작은 단위
      2. 0과 1을 가지고 있는 메모리를 구성하기 위한 작은 조각
      3. 이 조각들이 모여서 메모리가 만들어진다.
    2. 바이트
      1. 0과 1만 표현하는 비트를 모두 찾기는 부담
      2. 1→2→…→8개(새로운 단위:byte)
    3. 메모리(memo_ry): byte단위로 구성 모든 데이터는 byte 단위의 식별자인 메모리 주소값을 통해서 서로 구분

    식별자, 변수

    var testValue = 3

    변수 = 데이터

    식별자 = 변수명

    변수 선언과 데이터 할당

    /** 선언과 할당을 풀어 쓴 방식 */
    var str;
    str = 'test!';
    
    /** 선언과 할당을 붙여 쓴 방식 */
    var str = 'test!';
    
    • 값을 바로 변수에 대입하지 않는 이유(=무조건 새로 만드는 이유)
      • 이미 입력한 문자열이 길어진다면? 숫자는 항상 8byte로 고정이지만, 문자는 고정이 아니다.(영문:1.한글2)
      • 이미 1003주소에 할당된 데이터를 변환하려 할 때 훨씬 더 큰 데이터를 저장하려한다면, 1004주소 이후부터 저장되어잇는 모든 데이터를 오른쪽으로 다 미뤄야한다.
    • 메모리의 효율적 관리
      • 똑같은 데이터를 여러번 저장해야한다면? 1만개의 변수를 생성해서 모든 변수에 숫자 1을 할당하는 상황을 가정했을때 모든 변수를 별개로 인식한다고 하면, 1만개의 변수 공간을 확보해야 한다.
        • 바로 대입하는 숫자형은 8바이트 고정으로 1만개 * 8byte = 8만 byte
        • 변수 영역에 별도 저장하게되면 변수영역 : 2바이트 1만개 = 2만바이트만 차지하게된다. 💡변수영역은 데이터 영역보다 작기때문에 2로 가정함.
        • 데이터 영역 :8바이트 1개 = 8바이트
        • 변수영역에 별도로 저장하면 총 2만 8바이트만 든다.

    기본형 데이터와 참조형 데이터

    1. 메모리를 기준으로 다시한번 생각해보는 두 가지 주요 개념
      1. 변수 vs 상수
        1. 변수 : 변수 영역 메모리를 변경할 수 있음
        2. 상수 : 변수 영역 메모리를 변경할 수 없음
      2. 불변하다 vs 불변하지 않다
        1. 불변하다 : 데이터 영역메모리를 변경할 수 없음
        2. 불변하지 않다 : 데이터 영역 메모리를 변경할 수 있음
    2. 불변값과 불변성
    3. // a라는 변수가 abc에서 abcdef가 되는 과정을 통해 불변성을 유추해봅시다! // 'abc'라는 값이 데이터영역의 @5002라는 주소에 들어갔다고 가정할게요. var a = 'abc'; // 'def'라는 값이 @5002라는 주소에 추가되는 것이 아니죠! // @5003에 별도로 'abcdef'라는 값이 생기고 a라는 변수는 @5002 -> @5003 // 즉, "변수 a는 불변하다." 라고 할 수 있습니다. // 이 때, @5002는 더 이상 사용되지 않기 때문에 가비지컬렉터의 수거 대상이 됩니다. a = a + 'def';
    4. 참조형 데이터의 변수 할당 과정⬇️ 강의를 참고해서 아래 표를 직접 작성해보세요!주소 1001 1002 1003 1004
      데이터 objt/@7103~      
      주소 5001 5002 5003 5004
      데이터 1 ‘bbb’    
      주소 7103 7104 7105 7106
      데이터 a/@5001 b/@5002    
      조형 데이터가 불변하지 않다(가변하다)라고 하는 이유변경할 값이 숫자 2를 데이터 영역에 검색했는데 없을 경우 2를 새로 추가하고, 해당 @5003을 obj1을 위한 별도 영역에 갈아 껴준다.
    5. 데이터 영역에 저장된 값은 여전히 계속 불변값이지만 obj1을 위한 별도 영역은 얼마든지 변경이 가능해서 참조형 데이터를 흔히, 불편하지 않다(=가변하다)라고 한다.
    6. var obj1 = { a: 1, b: 'bbb', }; // 데이터를 변경해봅시다. obj1.a = 2;
    7. // 참조형 데이터는 별도 저장공간(obj1을 위한 별도 공간)이 필요합니다! var obj1 = { a: 1, b: 'bbb, };
    8. 중첩객체의 할당
      var obj = {
      	x: 3,
      	arr: [3, 4, 5],
      }
      
      // obj.arr[1]의 탐색과정은 어떻게 될까요? 작성하신 표에서 한번 찾아가보세요!
      
      ⬇️ 강의를 참고해서 아래 표를 직접 작성해보세요!주소 1001 1002 1003 1004 1005 …
      데이터 obj/@7103~          
      주소 5001 5002 5003 5004 5005
      데이터 3 4 5      
      주소 7103 7104 …
      데이터 x/@5001 arr/@8104~  
      주소 8104 8105 8106 …
      데이터 0/@5001 1/@5002 2/@5003  
      참조 카운트가 0인 메모리 주소의 처리
      1. 참조카운트란 무엇일까요?</aside>
      2. <aside> 💡 객체를 참조하는 변수나 다른 객체의 수를 나타내는 값입니다. 참조 카운트가 0인 객체는 더 이상 사용되지 않으므로, 가비지 컬렉터에 의해 메모리에서 제거됩니다.
      3. 가비지컬렉터(GC, Garbage Collector)</aside>
      4. <aside> 💡 더 이상 사용되지 않는 객체를 자동으로 메모리에서 제거하는 역할을 합니다. 자바스크립트는 가비지 컬렉션을 수행함으로써 개발자가 명시적으로 메모리 관리를 하지 않아도 되도록 지원합니다. 자바스크립트 엔진에서 내부적으로 수행되며, 개발자는 가비지 컬렉션에 대한 직접적인 제어를 할 수 없습니다.
      5. 변수 복사의 비교
      // STEP01. 쭉 선언을 먼저 해볼께요.
      var a = 10; //기본형
      var obj1 = { c: 10, d: 'ddd' }; //참조형
      
      // STEP02. 복사를 수행해볼께요.
      var b = a; //기본형
      var obj2 = obj1; //참조형
      
      주소 1001 1002 1003 1004 1005 …
      데이터 a/@5001 obj1/@7103~ b/@5001 obj2/@7103~    
      주소 5001 5002 5003 5004 5005  
      데이터 10 ‘ddd’        
      주소 7103 7104 …
      데이터 c/@5001 d/@5002  
      1. 복사 이후 값 변경(객체의 프로퍼티 변경
      // STEP01. 쭉 선언을 먼저 해볼께요.
      var a = 10; //기본형
      var obj1 = { c: 10, d: 'ddd' }; //참조형
      
      // STEP02. 복사를 수행해볼께요.
      var b = a; //기본형
      var obj2 = obj1; //참조형
      
      b = 15;
      obj2.c = 20;
      
      주소 1001 1002 1003 1004 1005 …
      데이터 a/@5001 obj1/@7103~ b/@5003 obj2/@7103~    
      주소 5001 5002 5003 5004 5005  
      데이터 10 ‘ddd’ 15 20    
      주소 7103 7104 …
      데이터 c/@5004 d/@5002  
      이렇게 되면 복사한 값은 변경이 잘 되지만 기존에 있던 데이터도 같이 변경이 되버린다.
      • 기본형
        • 숫자 15라는 값을 데이터 영역에서 검색 후 없다면 생성
        • 검색한 결과주소 또는 생성한 주소를 변수 영역 b에 갈아끼움
        • a와 b는 서로 다른 데이터 영역의 주소를 바라보고 있기 때문에 영향 없음
      • 참조형
        • 숫자 20이라는 값을 데이터 영역에서 검색 후 없다면 생성
        • 검색한 결과주소 또는 생성한 주소 obj2에게 지정되어 있는 별도 영역(7103~)에 갈아끼움
        • obj1도 똑같은 주소를 바라보고 있기 때문에 obj1까지 변경이 됨
      복사 이후 값 변경(객체 자체를 변경)주소 1001 1002 1003 1004 1005 …
      데이터 a/@5001 obj1/@7103~ b/@5003 obj2/@78104~    
      주소 5001 5002 5003 5004 5005  
      데이터 10 ‘ddd’ 15 20    
      주소 7103 7104 …
      데이터 c/@5001 d/@5002  
      주소 8104 8105 …
      데이터 c/@5004 d/@5002  
      obj2 변수는 참조형 데이터이고, 참조형 데이터의 값을 변경한 것임에도 불고하고 이전 케이스와는 다르게 obj1과는 바라보는 데이터 메모리 영역의 값이 달라진다.불변 객체의 정의객체 데이터 자체를 변경 하고자 한다면 기존 데이터는 변겨오디지 않는다. 즉 불변하다라고 볼 수 있다.
      // user 객체를 생성
      var user = {
      	name: 'wonjang',
      	gender: 'male',
      };
      
      // 이름을 변경하는 함수, 'changeName'을 정의
      // 입력값 : 변경대상 user 객체, 변경하고자 하는 이름
      // 출력값 : 새로운 user 객체
      // 특징 : 객체의 프로퍼티(속성)에 접근해서 이름을 변경했네요! -> 가변
      var changeName = function (user, newName) {
      	var newUser = user;
      	newUser.name = newName;
      	return newUser;
      };
      
      // 변경한 user정보를 user2 변수에 할당하겠습니다.
      // 가변이기 때문에 user1도 영향을 받게 될거에요.
      var user2 = changeName(user, 'twojang');
      
      // 결국 아래 로직은 skip하게 될겁니다.
      if (user !== user2) {
      	console.log('유저 정보가 변경되었습니다.');
      }
      
      console.log(user.name, user2.name); // twojang twojang
      console.log(user === user2); // true
      
      위 코드를 아래코드와 같이 개선할 수 있다.다만 위와 같은 방법은 속성이 적을땐 간단하게 변경이 가능하지만 속성이 많아질경우 문제가 된다.<패턴><적용>얕은 복사의 경우 중첩된 객체에 대해서는 완벽한 복사를 할 수 없다.
      • 얕은복사 : 바로 아래 단계의 값만 복사 문제점 : 중첩된 객체의 경우 참조형 데이터가 저장된 프로퍼티를 복사할 떄 주소값만 복사한다.
      var user = {
      	name: 'wonjang',
      	urls: {
      		portfolio: '<http://github.com/abc>',
      		blog: '<http://blog.com>',
      		facebook: '<http://facebook.com/abc>',
      	}
      };
      
      var user2 = copyObject(user);
      
      user2.name = 'twojang';
      
      // 바로 아래 단계에 대해서는 불변성을 유지하기 때문에 값이 달라지죠.
      console.log(user.name === user2.name); // false
      
      // 더 깊은 단계에 대해서는 불변성을 유지하지 못하기 때문에 값이 같아요.
      // 더 혼란스러워 지는거죠 ㅠㅠ
      user.urls.portfolio = '<http://portfolio.com>';
      console.log(user.urls.portfolio === user2.urls.portfolio); // true
      
      // 아래 예도 똑같아요.
      user2.urls.blog = '';
      console.log(user.urls.blog === user2.urls.blog); // true
      
      위와 같은 코드처럼 객체안에 객체는 가져올 수 가없다.
      • 깊은복사 : 내부의 모든 값들을 하나하나 다 찾아서 모두 복사하는 방법
      var user = {
      	name: 'wonjang',
      	urls: {
      		portfolio: '<http://github.com/abc>',
      		blog: '<http://blog.com>',
      		facebook: '<http://facebook.com/abc>',
      	}
      };
      
      // 1차 copy
      var user2 = copyObject(user);
      
      // 2차 copy -> 이렇게까지 해줘야만 해요..!!
      user2.urls = copyObject(user.urls);
      
      user.urls.portfolio = '<http://portfolio.com>';
      console.log(user.urls.portfolio === user2.urls.portfolio);
      
      user2.urls.blog = '';
      console.log(user.urls.blog === user2.urls.blog);
      
      객체의 프로퍼티 중, 기본형 데이터는 그대로 복사 + 참조형 데이터는 다시 그 내부의 프로퍼티를 복사한다. 이걸 재귀적 수행 이라고한다.
      var copyObjectDeep = function(target) {
      	var result = {};
      	if (typeof target === 'object' && target !== null) {
      		for (var prop in target) {
      			result[pop] = copyObjectDeep(target[prop]);
      		}
      	} else {
      		result = target;
      	}
      	return result;
      }
      
      //결과 확인
      var obj = {
      	a: 1,
      	b: {
      		c: null,
      		d: [1, 2],
      	}
      };
      var obj2 = copyObjectDeep(obj);
      
      obj2.a = 3;
      obj2.b.c = 4;
      obj2.b.d[1] = 3;
      
      console.log(obj);
      console.log(obj2);
      
      이렇게 하면 전체 다 복사가 가능하다
    9. 불변 객체
    10. 💡**재귀적으로 수행한다?** ⇒함수나 알고리즘이 자기 자신을 호출하여 반복적으로 실행되는 것을 말합니다 😎
    11. 깊은복사
    12. //위 패턴을 우리 예제에 적용해봅시다. var user = { name: 'wonjang', gender: 'male', }; var user2 = copyObject(user); user2.name = 'twojang'; if (user !== user2) { console.log('유저 정보가 변경되었습니다.'); } console.log(user.name, user2.name); console.log(user === user2);
    13. //이런 패턴은 어떨까요? var copyObject = function (target) { var result = {}; // for ~ in 구문을 이용하여, 객체의 모든 프로퍼티에 접근할 수 있습니다. // 하드코딩을 하지 않아도 괜찮아요. // 이 copyObject로 복사를 한 다음, 복사를 완료한 객체의 프로퍼티를 변경하면 // 되겠죠!? for (var prop in target) { result[prop] = target[prop]; } return result; }
    14. 얕은복사
    15. // user 객체를 생성 var user = { name: 'wonjang', gender: 'male', }; // 이름을 변경하는 함수 정의 // 입력값 : 변경대상 user 객체, 변경하고자 하는 이름 // 출력값 : 새로운 user 객체 // 특징 : 객체의 프로퍼티에 접근하는 것이 아니라, 아에 새로운 객체를 반환 -> 불변 var changeName = function (user, newName) { return { name: newName, gender: user.gender, }; }; // 변경한 user정보를 user2 변수에 할당하겠습니다. // 불변이기 때문에 user1은 영향이 없어요! var user2 = changeName(user, 'twojang'); // 결국 아래 로직이 수행되겠네요. if (user !== user2) { console.log('유저 정보가 변경되었습니다.'); } console.log(user.name, user2.name); // wonjang twojang console.log(user === user2); // false 👍
    16. 불변 객체의 필요성
    17. 객체의 속성에 접근해서 값을 변경하면 가변이 성립한다.
    18. 참조형 데이터가 ‘가변값’이라고 할 때의 ‘가변’은 참조형 데이터 자체를 변경할 경우가 아니라, 그 내부의 프로퍼티를 변경할 때 성립한다고 할 수 있다.
    19. //기본형 데이터 var a = 10; var b = a; //참조형 데이터 var obj1 = { c: 10, d: 'ddd' }; var obj2 = obj1; b = 15; obj2 = { c: 20, d: 'ddd'};
    20. 자바스크립트에서 중첩객체란, 객체 안에 또 다른 객체가 들어가는 것을 말해요. 이번 주차 초반에 살펴보았듯이 객체는 배열, 함수 등을 모두 포함하는 상위개념이기 때문에 배열을 포함하는 객체도 중첩객체라고 할 수 있답니다.

    undefined와 null

    둘 다 없음을 나타내는 값이다. 다만 목적이 다른다.

    undefined

    1. 변수에 값이 지되지 않는 경우, 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근했을때
    2. .이나 []로 접근하려 할 때, 해당 데이터가 존재하지 않는 경우
    3. return문이 없거나 호출되지 않는 함수의 실행 결과
    var a;
    console.log(a); // (1) 값을 대입하지 않은 변수에 접근
    
    var obj = { a: 1 };
    console.log(obj.a); // 1
    console.log(obj.b); // (2) 존재하지 않는 property에 접근
    // console.log(b); // 오류 발생
    
    var func = function() { };
    var c = func(); // (3) 반환 값이 없는 function
    console.log(c); // undefined
    

    null

    용도 : ‘없다’를 명시적으로 표현할 때

    주의 : typeof null

    typeof null이 object인 것은 유명한 javascript 자체 버그이다.

    var n = null;
    console.log(typeof n); // object
    
    //동등연산자(equality operator)
    console.log(n == undefined); // true
    console.log(n == null); // true
    
    //일치연산자(identity operator)
    console.log(n === undefined); //false
    console.log(n === null); // true
    

    실행컨텍스트(스코프,변수,객체,호이스팅)

    자바스크립트의 실행 컨텍스트는 실행할 코드에 제공할 환경정보를 모아놓은 객체이다.

    자바스크립트는 어떤 실행 컨텍스트가 활성화되는 시점에 다음과 같은 일을 한다.

    1. 선언된 변수를 위로 끌어올린다. = 호이스팅(hoisting)
    2. 외부 환경 정보를 구성한다.
    3. this값을 설정한다.

    실행 컨텍스트란?

    스택 vs 큐

    stack은 후입선출 느낌

    queue은 선입선출 느낌

    콜 스택 (call stack)

    동일 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 이것을 위에있는 스택의 한 종류인 콜스택에 쌓아올린다.

    가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장할 수 있다.

    1. 컨텍스트 구성
      1. 구성방법
        1. 전역공간
        2. eval()함수
        3. 함수(우리가 흔히 실행컨텍스트를 구성하는 방법)
    // ---- 1번
    var a = 1;
    function outer() {
    	function inner() {
    		console.log(a); //undefined
    		var a = 3;
    	}
    	inner(); // ---- 2번
    	console.log(a);
    }
    outer(); // ---- 3번
    console.log(a);
    

    이미지를 봤을때 코드실행 → 전역(in) → 전역(중단) + outer(in) → outer(중단) + inner(in) → inner(out) + outer(재개) → outer(out) + 전역(재개) → 전역(out) → 코드종료

    순서로 진행이 된다.

    결국 특정 실행 컨텍스트가 생성되는 시점이 콜 스택의 맨 위에 쌓이는 (노출되는) 순간을 의미한다.

    실행 컨텍스트 객체의 실체 (= 담기는 정보)

    1. VariableEnvironment 현재 컨텍스트 내의 식별자 정보(=record)를 갖고 있다.
      • 식별자 정보 var a = 3 위의 경우 var a를 의미한다.
      외부 환경 정보(=outer)를 갖고 있다. 선언 시점 LexicalEnvironment의 snapshot(생길때 그모습을 계속 간직한다)
    2. ⭐️LexicalEnvironment⭐️ 현재 컨텍스트 내의 식별자 정보(=record)를 갖고 있다.
      • 식별자 정보 var a = 3 위의 경우 var a를 의미한다.
      외부 환경 정보(=outer)를 갖고 있다. VariableEnvironment와 동일하지만, 변경사항을 실시간으로 반영한다.
    3. ThisBinding this 식별자가 바라봐야할 객체

    VariableEnvironment, LexicalEnvironment의 개요

    이 두가지는 담기는 항목은 완벽하게 동일하다. 그러나, 스냅샷 유지여부는 다르다.

    VE : 스냅샷을 유지한다.

    LE : 스냅샷을 유지하지 않는다. 즉, 실시간으로 변경사항을 계속해서 반영한다.

    결국, 실행 컨텍스트를 생성할 때, VE에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LE를 만들고 이후에는 주로 LE를 활용한다.

    구성요소

    1. VE, LE모두 동일하며, ‘environmentRecord’와 ‘outerEnvironmentReference’로 구성
    2. environmentRecord(=record)
      1. 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다.
      2. 함수에 지정된 매개변수 식별자, 함수자체, var로 선언된 변수 식별자 등
    3. outerEnvironmentReference(=outer)

    LexicalEnvironment(1) - environmentRocord(=record)와 호이스팅

    레코드는 식별자 정보

    • let a ;
      1. 복제의 방식
        1. 기본형 : 값이 담긴 주소값을 바로 복제
        2. 참조형 : 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
      2. 불변성의 여부
        1. 기본형 : 불변성을 띔
        2. 참조형 : 불변성을 띄지 않음
      메모리, 데이터
      1. 비트
        1. 컴퓨터가 이해할 수 있는 가장 작은 단위
        2. 0과 1을 가지고 있는 메모리를 구성하기 위한 작은 조각
        3. 이 조각들이 모여서 메모리가 만들어진다.
      2. 바이트
        1. 0과 1만 표현하는 비트를 모두 찾기는 부담
        2. 1→2→…→8개(새로운 단위:byte)
      3. 메모리(memo_ry): byte단위로 구성 모든 데이터는 byte 단위의 식별자인 메모리 주소값을 통해서 서로 구분
      식별자, 변수변수 = 데이터변수 선언과 데이터 할당
      • 값을 바로 변수에 대입하지 않는 이유(=무조건 새로 만드는 이유)
        • 이미 입력한 문자열이 길어진다면? 숫자는 항상 8byte로 고정이지만, 문자는 고정이 아니다.(영문:1.한글2)
        • 이미 1003주소에 할당된 데이터를 변환하려 할 때 훨씬 더 큰 데이터를 저장하려한다면, 1004주소 이후부터 저장되어잇는 모든 데이터를 오른쪽으로 다 미뤄야한다.
      • 메모리의 효율적 관리
        • 똑같은 데이터를 여러번 저장해야한다면? 1만개의 변수를 생성해서 모든 변수에 숫자 1을 할당하는 상황을 가정했을때 모든 변수를 별개로 인식한다고 하면, 1만개의 변수 공간을 확보해야 한다.
          • 바로 대입하는 숫자형은 8바이트 고정으로 1만개 * 8byte = 8만 byte
          • 변수 영역에 별도 저장하게되면 변수영역 : 2바이트 1만개 = 2만바이트만 차지하게된다. 💡변수영역은 데이터 영역보다 작기때문에 2로 가정함.
          • 데이터 영역 :8바이트 1개 = 8바이트
          • 변수영역에 별도로 저장하면 총 2만 8바이트만 든다.
      기본형 데이터와 참조형 데이터
      1. 메모리를 기준으로 다시한번 생각해보는 두 가지 주요 개념
        1. 변수 vs 상수
          1. 변수 : 변수 영역 메모리를 변경할 수 있음
          2. 상수 : 변수 영역 메모리를 변경할 수 없음
        2. 불변하다 vs 불변하지 않다
          1. 불변하다 : 데이터 영역메모리를 변경할 수 없음
          2. 불변하지 않다 : 데이터 영역 메모리를 변경할 수 있음
      2. 불변값과 불변성
      3. // a라는 변수가 abc에서 abcdef가 되는 과정을 통해 불변성을 유추해봅시다! // 'abc'라는 값이 데이터영역의 @5002라는 주소에 들어갔다고 가정할게요. var a = 'abc'; // 'def'라는 값이 @5002라는 주소에 추가되는 것이 아니죠! // @5003에 별도로 'abcdef'라는 값이 생기고 a라는 변수는 @5002 -> @5003 // 즉, "변수 a는 불변하다." 라고 할 수 있습니다. // 이 때, @5002는 더 이상 사용되지 않기 때문에 가비지컬렉터의 수거 대상이 됩니다. a = a + 'def';
      4. 참조형 데이터의 변수 할당 과정⬇️ 강의를 참고해서 아래 표를 직접 작성해보세요!주소 1001 1002 1003 1004
        데이터 objt/@7103~      
        주소 5001 5002 5003 5004
        데이터 1 ‘bbb’    
        주소 7103 7104 7105 7106
        데이터 a/@5001 b/@5002    
        조형 데이터가 불변하지 않다(가변하다)라고 하는 이유변경할 값이 숫자 2를 데이터 영역에 검색했는데 없을 경우 2를 새로 추가하고, 해당 @5003을 obj1을 위한 별도 영역에 갈아 껴준다.
      5. 데이터 영역에 저장된 값은 여전히 계속 불변값이지만 obj1을 위한 별도 영역은 얼마든지 변경이 가능해서 참조형 데이터를 흔히, 불편하지 않다(=가변하다)라고 한다.
      6. var obj1 = { a: 1, b: 'bbb', }; // 데이터를 변경해봅시다. obj1.a = 2;
      7. // 참조형 데이터는 별도 저장공간(obj1을 위한 별도 공간)이 필요합니다! var obj1 = { a: 1, b: 'bbb, };
      8. 중첩객체의 할당
        var obj = {
        	x: 3,
        	arr: [3, 4, 5],
        }
        
        // obj.arr[1]의 탐색과정은 어떻게 될까요? 작성하신 표에서 한번 찾아가보세요!
        
        ⬇️ 강의를 참고해서 아래 표를 직접 작성해보세요!주소 1001 1002 1003 1004 1005 …
        데이터 obj/@7103~          
        주소 5001 5002 5003 5004 5005
        데이터 3 4 5      
        주소 7103 7104 …
        데이터 x/@5001 arr/@8104~  
        주소 8104 8105 8106 …
        데이터 0/@5001 1/@5002 2/@5003  
        참조 카운트가 0인 메모리 주소의 처리
        1. 참조카운트란 무엇일까요?</aside>
        2. <aside> 💡 객체를 참조하는 변수나 다른 객체의 수를 나타내는 값입니다. 참조 카운트가 0인 객체는 더 이상 사용되지 않으므로, 가비지 컬렉터에 의해 메모리에서 제거됩니다.
        3. 가비지컬렉터(GC, Garbage Collector)</aside>
        4. <aside> 💡 더 이상 사용되지 않는 객체를 자동으로 메모리에서 제거하는 역할을 합니다. 자바스크립트는 가비지 컬렉션을 수행함으로써 개발자가 명시적으로 메모리 관리를 하지 않아도 되도록 지원합니다. 자바스크립트 엔진에서 내부적으로 수행되며, 개발자는 가비지 컬렉션에 대한 직접적인 제어를 할 수 없습니다.
        5. 변수 복사의 비교
        // STEP01. 쭉 선언을 먼저 해볼께요.
        var a = 10; //기본형
        var obj1 = { c: 10, d: 'ddd' }; //참조형
        
        // STEP02. 복사를 수행해볼께요.
        var b = a; //기본형
        var obj2 = obj1; //참조형
        
        주소 1001 1002 1003 1004 1005 …
        데이터 a/@5001 obj1/@7103~ b/@5001 obj2/@7103~    
        주소 5001 5002 5003 5004 5005  
        데이터 10 ‘ddd’        
        주소 7103 7104 …
        데이터 c/@5001 d/@5002  
        1. 복사 이후 값 변경(객체의 프로퍼티 변경
        // STEP01. 쭉 선언을 먼저 해볼께요.
        var a = 10; //기본형
        var obj1 = { c: 10, d: 'ddd' }; //참조형
        
        // STEP02. 복사를 수행해볼께요.
        var b = a; //기본형
        var obj2 = obj1; //참조형
        
        b = 15;
        obj2.c = 20;
        
        주소 1001 1002 1003 1004 1005 …
        데이터 a/@5001 obj1/@7103~ b/@5003 obj2/@7103~    
        주소 5001 5002 5003 5004 5005  
        데이터 10 ‘ddd’ 15 20    
        주소 7103 7104 …
        데이터 c/@5004 d/@5002  
        이렇게 되면 복사한 값은 변경이 잘 되지만 기존에 있던 데이터도 같이 변경이 되버린다.
        • 기본형
          • 숫자 15라는 값을 데이터 영역에서 검색 후 없다면 생성
          • 검색한 결과주소 또는 생성한 주소를 변수 영역 b에 갈아끼움
          • a와 b는 서로 다른 데이터 영역의 주소를 바라보고 있기 때문에 영향 없음
        • 참조형
          • 숫자 20이라는 값을 데이터 영역에서 검색 후 없다면 생성
          • 검색한 결과주소 또는 생성한 주소 obj2에게 지정되어 있는 별도 영역(7103~)에 갈아끼움
          • obj1도 똑같은 주소를 바라보고 있기 때문에 obj1까지 변경이 됨
        복사 이후 값 변경(객체 자체를 변경)주소 1001 1002 1003 1004 1005 …
        데이터 a/@5001 obj1/@7103~ b/@5003 obj2/@78104~    
        주소 5001 5002 5003 5004 5005  
        데이터 10 ‘ddd’ 15 20    
        주소 7103 7104 …
        데이터 c/@5001 d/@5002  
        주소 8104 8105 …
        데이터 c/@5004 d/@5002  
        obj2 변수는 참조형 데이터이고, 참조형 데이터의 값을 변경한 것임에도 불고하고 이전 케이스와는 다르게 obj1과는 바라보는 데이터 메모리 영역의 값이 달라진다.불변 객체의 정의객체 데이터 자체를 변경 하고자 한다면 기존 데이터는 변겨오디지 않는다. 즉 불변하다라고 볼 수 있다.
        // user 객체를 생성
        var user = {
        	name: 'wonjang',
        	gender: 'male',
        };
        
        // 이름을 변경하는 함수, 'changeName'을 정의
        // 입력값 : 변경대상 user 객체, 변경하고자 하는 이름
        // 출력값 : 새로운 user 객체
        // 특징 : 객체의 프로퍼티(속성)에 접근해서 이름을 변경했네요! -> 가변
        var changeName = function (user, newName) {
        	var newUser = user;
        	newUser.name = newName;
        	return newUser;
        };
        
        // 변경한 user정보를 user2 변수에 할당하겠습니다.
        // 가변이기 때문에 user1도 영향을 받게 될거에요.
        var user2 = changeName(user, 'twojang');
        
        // 결국 아래 로직은 skip하게 될겁니다.
        if (user !== user2) {
        	console.log('유저 정보가 변경되었습니다.');
        }
        
        console.log(user.name, user2.name); // twojang twojang
        console.log(user === user2); // true
        
        위 코드를 아래코드와 같이 개선할 수 있다.다만 위와 같은 방법은 속성이 적을땐 간단하게 변경이 가능하지만 속성이 많아질경우 문제가 된다.<패턴><적용>얕은 복사의 경우 중첩된 객체에 대해서는 완벽한 복사를 할 수 없다.
        • 얕은복사 : 바로 아래 단계의 값만 복사 문제점 : 중첩된 객체의 경우 참조형 데이터가 저장된 프로퍼티를 복사할 떄 주소값만 복사한다.
        var user = {
        	name: 'wonjang',
        	urls: {
        		portfolio: '<http://github.com/abc>',
        		blog: '<http://blog.com>',
        		facebook: '<http://facebook.com/abc>',
        	}
        };
        
        var user2 = copyObject(user);
        
        user2.name = 'twojang';
        
        // 바로 아래 단계에 대해서는 불변성을 유지하기 때문에 값이 달라지죠.
        console.log(user.name === user2.name); // false
        
        // 더 깊은 단계에 대해서는 불변성을 유지하지 못하기 때문에 값이 같아요.
        // 더 혼란스러워 지는거죠 ㅠㅠ
        user.urls.portfolio = '<http://portfolio.com>';
        console.log(user.urls.portfolio === user2.urls.portfolio); // true
        
        // 아래 예도 똑같아요.
        user2.urls.blog = '';
        console.log(user.urls.blog === user2.urls.blog); // true
        
        위와 같은 코드처럼 객체안에 객체는 가져올 수 가없다.
        • 깊은복사 : 내부의 모든 값들을 하나하나 다 찾아서 모두 복사하는 방법
        var user = {
        	name: 'wonjang',
        	urls: {
        		portfolio: '<http://github.com/abc>',
        		blog: '<http://blog.com>',
        		facebook: '<http://facebook.com/abc>',
        	}
        };
        
        // 1차 copy
        var user2 = copyObject(user);
        
        // 2차 copy -> 이렇게까지 해줘야만 해요..!!
        user2.urls = copyObject(user.urls);
        
        user.urls.portfolio = '<http://portfolio.com>';
        console.log(user.urls.portfolio === user2.urls.portfolio);
        
        user2.urls.blog = '';
        console.log(user.urls.blog === user2.urls.blog);
        
        객체의 프로퍼티 중, 기본형 데이터는 그대로 복사 + 참조형 데이터는 다시 그 내부의 프로퍼티를 복사한다. 이걸 재귀적 수행 이라고한다.
        var copyObjectDeep = function(target) {
        	var result = {};
        	if (typeof target === 'object' && target !== null) {
        		for (var prop in target) {
        			result[pop] = copyObjectDeep(target[prop]);
        		}
        	} else {
        		result = target;
        	}
        	return result;
        }
        
        //결과 확인
        var obj = {
        	a: 1,
        	b: {
        		c: null,
        		d: [1, 2],
        	}
        };
        var obj2 = copyObjectDeep(obj);
        
        obj2.a = 3;
        obj2.b.c = 4;
        obj2.b.d[1] = 3;
        
        console.log(obj);
        console.log(obj2);
        
        이렇게 하면 전체 다 복사가 가능하다
      9. 불변 객체
      10. 💡**재귀적으로 수행한다?** ⇒함수나 알고리즘이 자기 자신을 호출하여 반복적으로 실행되는 것을 말합니다 😎
      11. 깊은복사
      12. //위 패턴을 우리 예제에 적용해봅시다. var user = { name: 'wonjang', gender: 'male', }; var user2 = copyObject(user); user2.name = 'twojang'; if (user !== user2) { console.log('유저 정보가 변경되었습니다.'); } console.log(user.name, user2.name); console.log(user === user2);
      13. //이런 패턴은 어떨까요? var copyObject = function (target) { var result = {}; // for ~ in 구문을 이용하여, 객체의 모든 프로퍼티에 접근할 수 있습니다. // 하드코딩을 하지 않아도 괜찮아요. // 이 copyObject로 복사를 한 다음, 복사를 완료한 객체의 프로퍼티를 변경하면 // 되겠죠!? for (var prop in target) { result[prop] = target[prop]; } return result; }
      14. 얕은복사
      15. // user 객체를 생성 var user = { name: 'wonjang', gender: 'male', }; // 이름을 변경하는 함수 정의 // 입력값 : 변경대상 user 객체, 변경하고자 하는 이름 // 출력값 : 새로운 user 객체 // 특징 : 객체의 프로퍼티에 접근하는 것이 아니라, 아에 새로운 객체를 반환 -> 불변 var changeName = function (user, newName) { return { name: newName, gender: user.gender, }; }; // 변경한 user정보를 user2 변수에 할당하겠습니다. // 불변이기 때문에 user1은 영향이 없어요! var user2 = changeName(user, 'twojang'); // 결국 아래 로직이 수행되겠네요. if (user !== user2) { console.log('유저 정보가 변경되었습니다.'); } console.log(user.name, user2.name); // wonjang twojang console.log(user === user2); // false 👍
      16. 불변 객체의 필요성
      17. 객체의 속성에 접근해서 값을 변경하면 가변이 성립한다.
      18. 참조형 데이터가 ‘가변값’이라고 할 때의 ‘가변’은 참조형 데이터 자체를 변경할 경우가 아니라, 그 내부의 프로퍼티를 변경할 때 성립한다고 할 수 있다.
      19. //기본형 데이터 var a = 10; var b = a; //참조형 데이터 var obj1 = { c: 10, d: 'ddd' }; var obj2 = obj1; b = 15; obj2 = { c: 20, d: 'ddd'};
      20. 자바스크립트에서 중첩객체란, 객체 안에 또 다른 객체가 들어가는 것을 말해요. 이번 주차 초반에 살펴보았듯이 객체는 배열, 함수 등을 모두 포함하는 상위개념이기 때문에 배열을 포함하는 객체도 중첩객체라고 할 수 있답니다.
      undefined와 nullundefined
      1. 변수에 값이 지되지 않는 경우, 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근했을때
      2. .이나 []로 접근하려 할 때, 해당 데이터가 존재하지 않는 경우
      3. return문이 없거나 호출되지 않는 함수의 실행 결과
      var a;
      console.log(a); // (1) 값을 대입하지 않은 변수에 접근
      
      var obj = { a: 1 };
      console.log(obj.a); // 1
      console.log(obj.b); // (2) 존재하지 않는 property에 접근
      // console.log(b); // 오류 발생
      
      var func = function() { };
      var c = func(); // (3) 반환 값이 없는 function
      console.log(c); // undefined
      
      null주의 : typeof null
      var n = null;
      console.log(typeof n); // object
      
      //동등연산자(equality operator)
      console.log(n == undefined); // true
      console.log(n == null); // true
      
      //일치연산자(identity operator)
      console.log(n === undefined); //false
      console.log(n === null); // true
      

      실행컨텍스트(스코프,변수,객체,호이스팅)

      자바스크립트의 실행 컨텍스트는 실행할 코드에 제공할 환경정보를 모아놓은 객체이다.
      1. 선언된 변수를 위로 끌어올린다. = 호이스팅(hoisting)
      2. 외부 환경 정보를 구성한다.
      3. this값을 설정한다.
      실행 컨텍스트란?콜 스택 (call stack)가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장할 수 있다.
      1. 컨텍스트 구성
        1. 구성방법
          1. 전역공간
          2. eval()함수
          3. 함수(우리가 흔히 실행컨텍스트를 구성하는 방법)
      // ---- 1번
      var a = 1;
      function outer() {
      	function inner() {
      		console.log(a); //undefined
      		var a = 3;
      	}
      	inner(); // ---- 2번
      	console.log(a);
      }
      outer(); // ---- 3번
      console.log(a);
      
      결국 특정 실행 컨텍스트가 생성되는 시점이 콜 스택의 맨 위에 쌓이는 (노출되는) 순간을 의미한다.
      1. VariableEnvironment 현재 컨텍스트 내의 식별자 정보(=record)를 갖고 있다.
        • 식별자 정보 var a = 3 위의 경우 var a를 의미한다.
        외부 환경 정보(=outer)를 갖고 있다. 선언 시점 LexicalEnvironment의 snapshot(생길때 그모습을 계속 간직한다)
      2. ⭐️LexicalEnvironment⭐️ 현재 컨텍스트 내의 식별자 정보(=record)를 갖고 있다.
        • 식별자 정보 var a = 3 위의 경우 var a를 의미한다.
        외부 환경 정보(=outer)를 갖고 있다. VariableEnvironment와 동일하지만, 변경사항을 실시간으로 반영한다.
      3. ThisBinding this 식별자가 바라봐야할 객체
      VariableEnvironment, LexicalEnvironment의 개요VE : 스냅샷을 유지한다.결국, 실행 컨텍스트를 생성할 때, VE에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LE를 만들고 이후에는 주로 LE를 활용한다.
      1. VE, LE모두 동일하며, ‘environmentRecord’와 ‘outerEnvironmentReference’로 구성
      2. environmentRecord(=record)
        1. 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다.
        2. 함수에 지정된 매개변수 식별자, 함수자체, var로 선언된 변수 식별자 등
      3. outerEnvironmentReference(=outer)
      LexicalEnvironment(1) - environmentRocord(=record)와 호이스팅
      • let a ;
    • 레코드는 식별자 정보
    • 구성요소
    • LE : 스냅샷을 유지하지 않는다. 즉, 실시간으로 변경사항을 계속해서 반영한다.
    • 이 두가지는 담기는 항목은 완벽하게 동일하다. 그러나, 스냅샷 유지여부는 다르다.
    • 실행 컨텍스트 객체의 실체 (= 담기는 정보)
    • 순서로 진행이 된다.
    • 이미지를 봤을때 코드실행 → 전역(in) → 전역(중단) + outer(in) → outer(중단) + inner(in) → inner(out) + outer(재개) → outer(out) + 전역(재개) → 전역(out) → 코드종료
    • 동일 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 이것을 위에있는 스택의 한 종류인 콜스택에 쌓아올린다.
    • queue은 선입선출 느낌
    • stack은 후입선출 느낌
    • 스택 vs 큐
    • 자바스크립트는 어떤 실행 컨텍스트가 활성화되는 시점에 다음과 같은 일을 한다.
    • typeof null이 object인 것은 유명한 javascript 자체 버그이다.
    • 용도 : ‘없다’를 명시적으로 표현할 때
    • 둘 다 없음을 나타내는 값이다. 다만 목적이 다른다.
    • /** 선언과 할당을 풀어 쓴 방식 */ var str; str = 'test!'; /** 선언과 할당을 붙여 쓴 방식 */ var str = 'test!';
    • 식별자 = 변수명
    • var testValue = 3
Designed by Tistory.