입력, 연산, 출력
+ 전송, CPU에 최적화된 연산, 메모리의 사용을 최소화
변경될 수 있는 값을 말함.
변수를 만들 때 쓰는 keyword는 let(added in ES6), var, const가 있다.
let name = 'ryan';
console.log(name);
let이라는 keyword를 이용해서 name이라는 변수를 선언(declaration)했다. 그리고 선언함과 동시에 ryan이라는 변수의 값을 할당했다.
console 창에 ryan 출력
name = 'hello'
console.log(name);
다시 name이라는 변수에 hello라는 값을 다시 할당함
console 창에 hello 출력
{
let name = 'ryan';
console.log(name);
name = 'hello';
console.log(name);
}
console.log(name);
curly braces(중괄호)를 이용해서, block을 이용해서 코드를 block 안에 작성하게 되면 block 밖에서는 block 안에 있는 내용을 볼 수가 없게 된다. 즉, console을 이용해서 name을 출력하면 아무 값도 나오지 않는다.
block을 쓰지 않고, 파일 안에 바로 정의해서 쓰는 변수들.
let globalName = 'global name';
{
let name = 'ryan';
console.log(name);
name = 'hello';
console.log(name);
console.log(globalName); * 출력 됨
}
console.log(name);
console.log(globalName); * 출력 됨
global scope은 어느 곳에서나 접근이 가능
global scope 변수들은 application이 실행되는 순간부터 끝날 때까지 항상 메모리에 탑재되어있기때문에 최소한으로 쓰는 것이 좋고, 가능하면 class나 함수, if나 for loop, 필요한 부분에서만 정의해서 쓴는 것이 좋다.
(강의에서는 아직도 var를 쓰는 친구가 있다면 등을 한 대 SLAP! 하고, "쓰지마!"라고 하라고 하는데, 댓글 보니까 우리나라는 아직 많이 사용한다고 한다... ps.IE )
var을 쓰지 말아야하는 이유
1.var hoisting(move declaration form bottom to top)
console.log(age);
age = 4;
var age;
선언도 하기 전에 값을 할당하고, 값을 할당하기 전에도 값을 할당할 수 있다.
name = 4;
let name;
let를 쓰면 위 코드는 에러가 뜬다. 'let으로 선언하기 전에 값을 넣었잖아!'
2.has no block scope(block을 철저히 무시한다.)
{
age = 4;
var age;
}
console.log(age);
// Note!
// Immutable data types: primitive types, frozen objects (i.e obejct.freeze())
// Mutable data types: all obejcts by default are mutable in JS
한 번 할당하면 값이 절대 바뀌지 않는다.
const daysInWeek = 7;
const maxNumber = 5;
const monthsInYear = 12;
값이 계속 변경될 수 있는 것은 'Mutable Data Type, let처럼', 값이 변경될 수 없는 것은 'Immutable Data Type, const처럼'
C, JAVA 언어처럼 얼마나 사이즈를 할당할 것인지 생각할 필요없이 javascript는 number type만 사용하면 된다.
const count = 17; // integer, 정수
const size = 17.1 // decimal number, 10진수
console.log(`value: ${count}, type: ${typeof count}`); // value: 17, type: number
console.log(`value: ${size}, type: ${typeof size}`); // value: 17.1, type: number
대부분의 프로그래밍 언어에도 적용이 되어있듯이, 특별한 값이 미리 정해진 것이 있다.
const infinity = 1 / 0;
const negativeInfinity = -1 / 0;
const nAn = 'not a number' / 2;
console.log(infinity); // Infinity
console.log(negativeInfinity); // -Infinity
console.log(nAn); // NaN
연산할 때, 값이 valid한 값인지 확인하고 연산하는 것이 중요하다.
javascript에서 number는 -253 ~ 253까지 범위의 숫자만 표현이 가능한데, 최근에 bigInt라는 type이 추가되었다. 두 번재 코드 처럼 숫자 끝에 n만 붙이면 type이 number가 아닌 bigInt로 간주되어진다.
const bigInt = 1234567890123456789012345678901234567890; // over (-2**53 ~ 2**53)
console.log(`value: ${bigInt}, type= ${typeof bigInt}`); // value: 1.2345678901234568e+39, type= number
Number.MAX_SAFE_INTEGER;
const bigInt = 1234567890123456789012345678901234567890n; // over (-2**53 ~ 2**53)
console.log(`value: ${bigInt}, type= ${typeof bigInt}`); // value: 1234567890123456789012345678901234567890, type= bigint
Number.MAX_SAFE_INTEGER;
다른 프로그래밍 언어에서 한 가지의 character만 들어있는 data type이 따로있지만, javascript에서는 한 가지의 글자든, 여러개의 글자든 모두 다 string type으로 할당이 되고, 일반 string과 다른 변수를 '+'기호를 이용해서 string 연결할 수 있다.
const char = 'c';
const brendan = 'brendan';
const greeting = 'hello ' + brendan;
console.log(`value: ${greeting}, type: ${typeof greeting}`);
const helloBob = `hi ${brendan}!`; //template literals (string)
-> ``(backtick)을 사용해서 string(hi)을 적고, $기호와 {}를 이용하면, 변수의 값(brenden)이 자동적으로 붙여져서 나온다.
console.log(`value: ${helloBob}, type: ${typeof helloBob}`); // hi brendan!, type: string
console.log(`value: ${helloBob}, type: ${typeof helloBob}`);
console.log('value: ' + helloBob + ',' + ' type: ' + typeof helloBob);
-> ``(backtick)을 사용하지않는 기존의 출력 방법은 번거롭다.
True(참), False(거짓)
false: 0, null, undefined, NaN, ''
true: any other value
const canRead = true;
const test = 3 < 1; // false
console.log(`value: ${canRead}, type: ${typeof canRead}`); // value: true, type: boolean
console.log(`value: ${test}, type: ${typeof test}`); // value: false, type: boolean
let nothing = null;
console.log(`value: ${nothing}, type: ${typeof nothing}`); // value: null, type: object
-> null이라고 할당하는 경우에는 nothing이라는 변수가 텅텅비어있는 empty 값이라는 것을 지정해주는 것.
let x;
let x = undefined; // let x;와 같은 경우라고 보면 됨.
console.log(`value: ${x}, type: ${typeof x}`); // value: undefined, type: undefined
-> 선언은 되었지만 값이 지정되어있지않다.
symbol은 나중에 다른 자료구조에서 고유한 식별자가 필요하거나, 아니면 동시에 다발적으로(concurrently) 일어날 수 있는 코드에서 우선순위를 주고 싶을 때 사용. 간혹, 식별자를 string을 사용해서 쓰는 경우가 있는데, string은 다른 모듈이나 다른 파일에서 동일한 string을 썼을 때, 동일한 식별자로 간주된다. 하지만, 반대로 symbol 같은 경우에는 동일한 (밑에 코드) 'id'를 이용해서 symbol을 만들었지만, 이 두가지의 symbol은 다른 경우다.
const symbol1 = Symbol('id');
const symbol2 = Symbol('id');
console.log(symbol1 === symbol2); // false
-> 동일한 지 확인
만약에 string을 같은 것을 사용하고, 동일한 symbol을 사용하고 있다면,
const gsymbol1 = Symbol.for('id');
const gsymbol2 = Symbol.for('id');
console.log(gsymbol1 === gsymbol2); // true
console.log(`value: ${symbol1}, type: ${typeof symbol1}`); // ... Cannot covert a Symbol value to a string at...
console.log(`value: ${symbol1.description}, type: ${symbol1}`); // value: id, type: symbol
-> 우리가 일상생활에서 보는 물건과 물체들을 대표할 수 있는 Box형태를 말한다. 그냥 변수, name, age는 아무것도 설명이 되지않지만, 'ryan', 100이라는 object를 만들어서 ryan의 이름은 ryan이고, 나이는 100살이라고 할 수 있다.
const ryan = { name: 'ryan', age: 100 };
-> ryan은 const로 지정되어있어서, 한 번 할당된 object는 다시는 변경이 불가하다. 하지만, ryan object 안에는 name과 age라는 변수들이 존재해서 ryan.name, ryan.age, 이런식으로하면 각 변수가 가리키는 memory에 다른 값으로 할당이 가능하다.
그래서,
const ryan = {
name: 'ryan',
age: 100
};
ryan.age = 20;
-> ryan의 age는 20이라고 변경이 가능하다.
Primitive type과 Object type은 type에 따라서 value(값) 다른 방식으로 저장된다.
primitive type은 value(값) 자체가 메모리에 저장된다.let name = ryan; // ryan이 메모리에 바로 저장된다.
object type 너무 커서 메모리에 한 번에 다 저장될 수 없다.
const ryanInfo = { name: 'ryan', 'age: 32' };
const ryanInfo라고 선언하고, object를 할당하게 되면, ryanInfo가 가리키는 곳에는 ref(reference)가 있다. ref는 실제로 object를 가리키고 있는 곳이다. 이 ref를 통해서 실제로 object 담겨있는 메모리를 가리키게 되는 것이다. 그래서 const ryanInfo라고 하면, ryanInfo가 가리키는 ref만 잠겨서 ryanInfo가 다른 object로 변경하는 것이 불가능하지만, ryanInfo의 name과 age를 바꿀 수 있는 것은 이 이유 중에 하나이다.
-> 따라서, primitive type은 value로 값이 저장되고, object type은 object가 가리키는 ref에 메모리에 저장된다라고 이해하면된다.
C, JAVA 언어는 static typed language.
-> 변수를 선언할 때, 어떤 타입인지 결정해서 type을 같이 선언한다.
javascript 언어는 선언할 때, 어떤 타입인지 선언하지않고, run time, 프로그램이 동작할 때, 할당된 값에 따라서 type이 변경될 수 있다는 것을 얘기한다. 이런 dynamic typed language는 좋은 아이디어가 있을 때, 빠르게 프로토타입을 하기에는 유용하게 쓸 수 있는 언어지만, 다수의 엔지니어들 아니면 어느 정도 규모가 있는 프로젝트를 만들 때, dynamic typed 대문에 발에 불똥이 떨어질 수 있다.
예시)
let text = 'hello';
console.log(`value: ${text}, type: ${typeof text}`); // value: hello, type: string
-> 'hello'라는 string을 할당하게 되면, text는 string이라는 변수가 된다.
text = 1;
console.log(`value: ${text}, type: ${typeof text}`); // value: 1, type: number
-> text에 다시 숫자 1을 할당하게 되면, type이 number로 변경이 된다.
text = '7' + 5;
console.log(`value: ${text}, type: ${typeof text}`); // value: 75, type: string
-> text에 '7' + 5; 를 할당하면, javascript engine에서 string('7')에 더하기가 있어서 number(5)를 string으로 변환해서 string + string을 해주게 되어 sting으로 type이 변환되면서 75가 된다.
text = '8' / '2';
console.log(`value: ${text}, type: ${typeof text}`); // value: 4, type: number
-> number가 들어있는 string에 나누기 연산자를 입력했네? 그럼 number와 number를 나누자! 그래서 type이 number가 되버린다.
=> Dynamic typing 때문에 뒤통수를 많이 얻어맞아서, TS(TypeScript, javascript 위에 type이 올려져서 나온 언어)가 나오게 된다.
### words
>- hoist: 끌어올려주다.
- hoisting: 어디에 선언했냐에 상관 없이, 항상 제일 위로 선언을 끌어올려주는 것.
- constant: 일정한, 불변의, 상수
- mutable: 변하기 쉬운
- immutable: 불변의