스터디/개인스터디

#009 자바스크립트 200제 - 스코프체인

d0201d 2020. 12. 10. 23:05

스코프체인

- ES6부터 나온 문법으로 배열이나 객체의 값을 새로운 병수에 쉽게 할당 가능

 

# 실행 컨텍스트

- 코드가 실행되기 위해 필요한 정보를 가지고 있음. 이 실행 컨텍스트는 실행 가능한 코드가 실행될때 생성.

- 대표적으로 실행가능한 코드는 전역함수와 함수코드가 있음 (+ eval, 모듈코드 등)

1. 전역코드 실행
2. 전역 컨텍스트를 만들고 전역코드를 순차적으로 평가
3. 그러다 함수가 호출문을 만나면 새로운 실행 컨텍스트가 생성되면서 해당 함수 안의 코드를 순차적으로 평가
4. 이때 스택을 이용해 실행 컨텍스트를 관리하게 되는데
    새로운 실행 컨텍스트가 생성되면 스택에 쌓고, 종료되면 스택에서 해당 실행 컨텍스트를 제거함
var person = 'harin';

function print() {
    var person2 = 'jay';

    function innerPrint() {
        console.log(person); //harin
        console.log(person2); //jay
    }

    innerPrint();
    console.log('print finished');
}

print();
console.log('finished');

 

# 렉시컬 환경

> 환경레코드

> 외부 렉시컬 환경

ExecutionContext = {
	LexicalEnvironment : {
    	EnvironmentRecord : {
       
       },
       OuterLexicalEnvironment : 참조
    } 
}

 

 

클로저(Closure)

- ES6부터 나온 문법으로 배열이나 객체의 값을 새로운 병수에 쉽게 할당 가능

function createCounterClosure() {
    let count = 0;
    return {
        increase: function() {
            count++;
        },
        getCount: function() {
            return count;
        }
    };
}

const counter1 = createCounterClosure();
const counter2 = createCounterClosure();

counter1.increase();
counter1.increase();
console.log('counter 1의 값 : ' + counter1.getCount());   //2
counter2.increase(); 
console.log('counter 2의 값 : ' + counter2.getCount());   //1

 

 

객체 속성 (Object Property)

- 자바스크립트의 모든 객체속성은 자기 자신에 대한 정보를 담고있는 속성 기술자(Property Descriptor)를 가지고 있음

- Object.getOwnPropertyDescriptor를 통해 속성 기술자 객체를 가지고 올 수 있음.

- Object.defineProperty를 통해 해당 객체의 속성을 정의

let user = {
    name: "jeado"
};
let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
console.log(descriptor);

let user2 = {};
Object.defineProperty(user2, "name", { //속성을 정의할 객체//속성명//속성기술자{}
    value: "jeado", //값
    enumerable: true, // 나열가능여부
    configurable: true, // 속성 기술자를 변경할 수 있는 여부 (false일 경우 속성 기술자를 다시는 변경할수 없음)
    writable: false //값을 변경 할수 있는 여부
});
console.log(user2.name); //jeado
user2.name = "bbo";
console.log(user2.name); //jeado  ?  writable를 false로 줬기 때문에 재할당해도 콘솔에 바뀌지 않고 기존값이 출력

let user3 = {
    name: "jeado",
    toString() {
        return this.name;
    }
};
Object.defineProperty(user3, "toString", {
    enumerable: false //toString 출력되지 않음
});
for (let key in user3) {
    console.log(key)
}

let user4 = {};
Object.defineProperty(user4, "name", {
    value: "jeado",
    configurable: false //delete를 통해 속성값을 지우려해도 지워지지 않고 리턴 
});
delete user4.name
console.log(user4);
Object.defineProperty(user4, "name", {
    writable: true
});



//{value: "jeado", writable: true, enumerable: true, configurable: true}
//jeado
//jeado
//name
//{name: "jeado"}
// Uncaught TypeError: Cannot redefine property: name
    at Function.defineProperty (

 

Get, Set

- 속성기술자를 통해 해당 객체의 속성을 정의하는데 이때 값에 접근하는 방식을 접근 기술자라고 하고 get과 set을 메서드로 가  짐

- get 메서드는 속성에 접근할때 호출

- set 메서드는 속성에 값을 대입할때 호출

let user = {};
Object.defineProperty(user, "age", {
    get: function() {
        return this._age;
    },
    set: function(age) {
        if (age < 0) {
            console.log('Error : 0보다 작은값입니다')
        } else {
            this._age = age;
        }
    },
    enumerable: true
});
user.age = 10;
console.log(user.age);
user.age = -1;

let user2 = {
    get name() {
        return this._name;
    },
    set name(val) {
        if (val.length < 3) {
            throw new Error('Error : 3자 이상이어야 합니다');
        }
        this._name = val;
    }
}

user2.name = 'harin';
console.log(user2.name);
user2.name = 'ha';


//10
//Error : 0보다 작은값입니다
//harin
//Uncaught Error: Error : 3자 이상이어야 합니다