자바스크립트 중급 (변수~심볼)

Junho Yun·2022년 11월 14일
0

하루만에배우기

목록 보기
4/11
post-thumbnail

변수

let, var, const의 차이점

let과 const는 최근에 추가된 문법이며, 이전에는 var를 사용했습니다.
let과 var는 거의 대부분의 경우에 같은 역할을 합니다.

var name1 ='mike';
console.log(name); // mike

var name1 = 'michael';
console.log(name); // michael

let name2 ='mike';
console.log(name); // mike

let name2 = 'michael';
console.log(name); // 에러 발생

차이점은 var는 한번 선언된 변수를 다시 선언할 수 있습니다.
let의 경우에는 다시 선언할 경우 error가 발생합니다.

var name1;
console.log(name1); // undefined 초기화
name1 = 'mike';

console.log(name2); // error , TDZ 할당전 사용 불가
let name2 = 'mocha';

var는 선언하기 전에 사용할 수 있습니다 (호이스팅)
이 때 선언은 호이스팅 되지만 할당은 호이스팅되지 않기 때문에 undefined를 반환합니다. let도 호이스팅 되지만 error를 발생합니다.
그 이유는 (Temporal Dead Zone)TDZ 때문입니다. let과 const는 TDZ의 영향을 받아 선언 전에 사용할 수 없습니다.

let age = 30;

fuction showAge() {
	cosole.log(age);	// error 발생, TDZ
    
    let age = 20; // 호이스팅 -> 스코프는 함수 
}

위는 let이 호이스팅 된다는 것을 모여주는 코드 입니다.
만약 호이스팅이 되지 않는다면, 함수 외부에서 할당한 30이 log에 찍히겠지만, 호이스팅과 TDZ에 인해 error를 발생할 것 입니다.

호이스팅 : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 동작하는 것

변수의 생성과정

var
1. 선언 및 초기화 단계 (선언과 동시에 undefined로 초기화)
2. 할당 단계

let
1. 선언 단계 (호이스팅)
2. 초기화 단계
3. 할당 단계

const
1. 선언+초기화+할당
(let 과 var는 선언만 해놓고 나중에 변수를 넣을 수 있지만 const는 선언과 동시에 할당을 해야합니다.)

    let name;
    name = 'mike';
    
    var age;
    age = 33;
    
    const gender;	// 선언 때 할당을 안해서 error 발생
    gender = 'male';
    

스코프

var : 함수 스코프 (function scoped)

let, const : 블록 스코프 (block scoped)
함수, if문, for문, while문, try/catch문 등

function add() {
	// block level scoped
}

if() {
	// block level scoped
}

블록 스코프란 코드블럭 내부에서 선언된 변수는 해당 코드블럭 안에서만 동작 할 수 있는 것을 뜻합니다.

const age = 33;
if)(age>19){
	var txt = '성인';
}
console.log(txt); // '성인' var로 선언했기 때문에 가능

function add (num1, num2){
	var result = num1 + num2;
}

add(2,3);
console.log(result); 
// error 발생 : 
//		var가 유일하게 벗어날 수 없는 스코프가 있습니다. 바로 함수 스코프 입니다.

생성자 함수

객체 리터럴

let user = {
	name : 'mike';
    age : 30,
} // 객체를 만드는 방법

위의 코드는 객체를 만드는 기본적인 방법입니다.
위와 같은 객체가 여러개가 필요하다면? 사용하는 것이 생성자 함수 입니다.

fuction User(name, age){
// User 에서 첫글자가 대문자 인 것은 생성자 함수임을 알려주는 장치임.
    this.name = name;
    this.age = age;
}

let user1 = new User('mike',30);
let user2 = new User('jun',14);
let user3 = new User('ho',18);
// new 연산자를 사용해서 호출해 줍니다.

위의 코드로 순식산에 서로 다른 3개의 객체를 만들어 줍니다.

구체적 동장 방식

fuction User(name, age){
	// this = {}
    this.name = name;
    this.age = age;
	//	return this;
}

new User();

new로 함수를 호출하면 발생하는 일
1. 함수 내부에서 this 라는 객체를 만듭니다 (코드에는 없지만)
2. 코드에 있는 값들을 this에 저장합니다. (this.name, this.age)
3. this를 반환합니다. (코드에는 없지만 ^^)

빠르고 일관성있는 여러개의 객체를 만들 수 있는 방법입니다.
객체 안에 메소드를 추가할때도 같은 방식으로 동작합니다.

객체 메소드, 계산된 프로퍼티

let a = 'age';

const user = {
	name = 'mike';
    [a] : 30 // age : 30, computed property
}

function makeObj(key, val){
	return {
    	[key] : val,
    }
}

const obj = makeObj("나이",33);
// "나이"가 키가 되고, 33은 값이됩니다. 어떤 것이 키가 될지 모를때 유용
console.log(obj);

객체에서 사용할 수 있는 메소드 리스트

  • Object.assign() : 객체 복사
  • Object.Keys() : 키를 배열로 반환
  • Object.values() : 값을 배열로 반환
  • Object.entries() : 키/값 을 배열로 반환
  • Object.fromEntries()
const user = {
	name : 'mike';
    age : 33,
}

const newUser = Object.assign({},user); // 객체 복사

newUser.name = 'top';

console.log(newUser.name); // top -> 변경 완료
console.log(user.name); // mike -> 기존 객체는 값 유지

Object.assign()는 객체의 값을 복사해서 "새로운 객체"를 만들어 줍니다. 위의 코드에서 보면 name 값을 바꿔도 기존 객체에는 영향을 주지 않는 것을 볼 수 있습니다.

const user = {
	name : 'mike'
}
const info1 = {
	age : 33
}
const info2 = {
	gender : 'male'
}

Object.assign(user,info1,info2)

위의 코드 처럼 여러개의 객체를 한번에 합쳐서 새로운 객체를 만들 수도 있습니다.

const user = {
	name : 'mike',
    age : 30,
    gender : 'female',
}

Object.keys(user);
// ["name","age","gender"]
Object.values(user);
// ["mike",30,"female"]

Object.entries(user);
// 
[
	["name","mike"],
	["age",30],
    ["gender","female"]
]
//

Object.keys 는 객체의 키를 배열로 만들어서 반환 합니다.
Object.values 는 객체의 값을 배열로 만들어서 반환 합니다.
Object.entries 는 객체의 키와 값을 배열로 만들어서 반환
Object.fromEntries 는 키/값 배열을 객체로 변환 (entries와 반대)

심볼

심볼을 언제 쓰는가

지금까지 객체의 프로퍼티 키는 문자열로 만들었습니다. 하지만 문자열 말고 가능한 것이 있습니다. 그것이 바로 심볼입니다.

//유일성 보장의 예시
const sym1 = Symbol();
const sym2 = Symbol('foo');
const sym3 = Symbol('foo');
// 3개의 심볼을 만들었습니다. sym2와 sym3는 보기에는 같아보이죠

Symbol('foo') === Symbol('foo')  // false 
// 유일성 보장으로 서로 다릅 값이라는 것 입니다.

심볼은 언제 사용할까요? 바로 유일한 식별자로 사용할 때 사용합니다.
주 역할이 유일성 보장이라고 할 수 있습니다.

// 이미 존재 or 다른 팀원이 만들 객체
const user = {
	name : 'mike',
    age : 30,
}

// 내가 작업하는 부분
// user.showName = fuction() {};  -> 이렇게하면 꼬이게 되겠죠
const showName = Symbol('show name');  // 심볼을 선언하는 방법
user[showName] = fuction() {
	console.log(this.name);
};

user[showName]


// 사용자가 접속하면 보는 메시지
for(let key in user){
	console.log(`his ${key} is ${user[key]}.`);
}

유일성을 갖는 다는 것이 왜 중요할까요?
협업을 할때 각자가 컨트롤하는 객체가 있을 수 있고, 해당 이름을

심볼 관련 메소드

symbol.for() : 전역 심볼

  • 하나의 심볼만 보장 받을 수 있음
  • 없으면 만들고, 만약 이미 있으면 가져오기 때문
  • symbol 함수는 매번 다른 symbol 값을 생성한다. 하지만
  • symbol.for 메소드는 하나를 생성한 뒤 키를 통해 같은 symbol을 공유한다
const id1 = Symbol.for('id');
const id2 = Symbol.for('id');

id1 === id2; // true

Symbol.keyFor(id1) // 'id'

const pw = Symbol('pw 입니다.');
id.description; // "pw 입니다."

전역 심볼의 경우 생성할 때 적어주었던 이름은 keyFor을 통해 알 수 있다.

전역 심볼이 아닐경우에는 description을 통해 할 수 있습니다.

숨겨진 Symbol key 보는 법

const id = Symbol('id');

const user = {
	name : 'mike',
    age : 30,
    [id] : 'myid',
}

Object.getOwnPropertySymbols(user); // [Symbol(id)]
Reflect.ownKeys(user); // ["name"],"age",Symbol(id)]

심볼을 완전 숨길 수는 없고 위의 코드처럼 확인할 수 있습니다.

심볼 쉬운 듯하지만 이해가 더욱 필요할 것 같습니다.

profile
의미 없는 코드는 없다.

0개의 댓글