스코프

모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할수 있는 유효범위가 결정 -> 이게 스코프

var x = 'gloabal';

funciton foo() {
  var x = 'local';
  console.log(x);
}

foo() // local
console.log(x) // global

JS 가 식별자를 결정하는 방법: 참조된 위치 기준으로 가장 가까운 스코프에서 선언된 변수를 참조.

같은 스코프 내에서 중복선언 불가! var 제외...

전역 변수는 어디서든지 참조할 수 있다

지역 변수는 자신의 지역 또는 하위 지역에서 유효하다. 안에서 바깥은 참조하는 것은 가능하지만, 밖에서 안을 참조하는게 안됨.

스코프 체인. 변수가 참조되면, 참조하는 스코프에서 해당 변수의 선언 여부를 검색. 없네? 상위 스코프로 이동. 같은 작업 반복.
부모와 자식 관계인 상속과도 유사. 자식이 부모의 자원을 사용하는 것은 용납, 부모가 자식의 자원을 이용하는건 ㄴㄴ

블록레벨 (if, for, while, try/catch)

렉시컬 스코프

자바스크립트에서는 함수가 어디서 정의했는지에 따라 상위 스코프를 결정. 전역에서 정의된 함수라면, 그들의 상위 스코프는 어디서 호출되었는지랑 관계 없이 항상 전역.

var x = 1;

function foo(){
  var x = 10;
  bar();
}

function bar(){
  console.log(x);
}

foo() // 1 bar 를 foo 스코프 안에서 참조하고 있지만, 이건 중요하지 않다... 중요한건 bar 는 전역에서 정의된 함수라는 것!
bar() // 1

전역변수

보통 지역변수는 참조가 안되면 죽어 -> 전역은 영원히 메모리를 차지하는...

아무도 지역 스코프가 차지하는 메모리 공간을 참조하지 않으면, 가비지 콜렉터 등장..!
함수 내부에서도 호이스팅 발생...
변수의 수명은 해당 스코프의 생명주기와 일치...
지역 변수의 생명주기: 등록된 스코프가 소멸할 때까지
전역 변수의 생명주기: 페이지 닫힐 때 까지

  1. 암묵적 결합: 누구나 참조할 수 있다는 점은, 해당 변수의 변화흐름을 명시적으로 파악하기 어려움
  2. 긴 생명 주기: 메모리 리소스 오래 소비
  3. 스코프 체인 상 종점: 변수를 참조할 때, 스코프 단위로 차례로 검색. 전역변수는 종점이니까, 가장 마지막에 검색됨.
  4. 네임스페이스 오염... 다른 파일에서도 전역 변수는 참조 가능...

변수의 스코프는 좁으면 좁을수록 좋아! => 무분별한 전역 변수를 줄이자

  1. 즉시 실행 함수로 일회성 변수 생성
  2. 네임스페이스 객체: 전역에 네임스페이스 객체 만들어. 전역으로 만들 변수는 해당 객체에 저장. 네이밍 적으로 구분해서 다른 파일에서 전역 건들지 마! const = myApp = {}. myApp.
  3. 모듈 패턴: 클로져와 함께...! 정보 은닉과 캡술화 가능!
  4. es6. type = 'module'

함수선언 키워드와 스코프

위클리 페이퍼 블로그 참조

프로퍼티 어트리뷰트

내부 로직관련 내용이네.
[[prototype]] 이라는 내부 슬롯은 모든 객체가 가져. 원칙적으로 접근 불가하나, __proto__ 이런 식으로 간접적인 접근 가능.

프로퍼티의 상태: value / writable / enumerable / configurable

const person = { name: 'Lee', 생일: '' }; length 2 / for in, 

console.log(Object.getOwnPropertyDescriptor(person, 'name'))
// { value: 'Lee', writable: true, enumerable: true, configurable: true }
  1. value: person.name = '' 하면 밸류 프로퍼티에 동적으로 할당 및 재할당. 얘는 변수가 아닌걸? 이걸 가능케 하는 로직이 내부적으로 있다.
  2. writable: 프로퍼티 값의 변경 여부. 얘가 false 면 value 값은 변경 X, 읽기 전용
  3. enumerable: 프로퍼티 열거 가능. FALSE 면 for in 문이나, Object.kyes 메서드로 열거 불가능. length = 5인데 for in 할 때는 4개만 나오거나 그러겠지?
  4. configurable: 프로퍼티 재정의 가능 여부. false 면 프로퍼티 삭제나 프로퍼티 어트리뷰트 (value, writable, enumerable) 변경 불가 (예외 하나 있긴 함)

접근자 프로퍼티의 경우... get/ set/ enumerable/ configurable

사실상 getter/setter 위해 있음. 객체에 키값줘서 밸류에 접근할 수 있지만, 캡슐화 위해 getter/setter 함수로 객체 내 값 변경 추이를 확인하기 쉬움.
1. getter 동작할 때: 먼저 프로퍼티 키값 유효성 확인 / 프로토타입 체인에서 프로퍼티 검색 / 검색된 프로퍼티가 데이터 프로퍼티인지 접근자인지 확인 / 접근자 프로퍼티 어트리뷰트인 GET, getter 함수 호출해서 결과 반환

프로퍼티 정의는: Object.defineProperty(<객체명>, <원하는 키값>, { value: 'Lee', writable: true, enumerable: true, configurable: true })

객체 변경 방지: preventExtensions/ seal/ freeze

  1. preventExtensions: 프로퍼티 추가만 막아
  2. seal: 프로퍼티 추가, 삭제, 프로퍼티 어트리뷰트 재정의 막아 -> getter, setter 는 가능
  3. freeze: 프로퍼티 추가, 삭제, 프로퍼티 어트리뷰트 재정의에 더해 프로퍼티 값 쓰기도 막아 -> getter 만 가능

근데 이건 표면에 있는 객체만 동결하지, 객체 안에 객체가 있는 중복 구조에서는 모든 객체의 동결 보장 ㄴㄴ
-> 완전히 불변하는 객체를 만들기 위해서는 freeze 를 재귀적으로 모든 객체에 적용

profile
우리 인생 화이팅~

0개의 댓글