자바스크립트는 loosely type의 동적언어.
- JavaScript 형변환이란?
함수 또는 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환 됨, 이러한 과정을 형 변환(type conversion)이라고 칭하며, alert가 전달받은 값은 자료형과 관계없이 이를 문자열로 자동변환하여 보여주는 것과 수학 관련 연산자가 전달받은 값을 숫자로 변환하는 경우가 형 변환의 대표적인 예시
'암시적변환'
'명시적변환'
- ==, ===의 차이점
자바스크립트에서는 값을 비교하기 위해 ==이라는 연산자와 ===연산자를 사용.
두 연산자는 값이 일치하는 경우 true를 반환하며 , 값이 일치하지 않으면 false를 반환
== 연산자는 값의 타입이 다를 경우, 자동으로 일부 피연산자의 타입을 변환하여 값을 비교함
500 == 500//true500 == '500'//true #하나는 숫자형, 하나는 문자열이면 문자열을 숫자로 변환 후 값을 비교true == 1//true #불리언 값이 존재하는 경우, 불리언 값을 1로 변환 후 값을 비교true == '1'//true #불리언 값을 1로 변환하면 1=='1'이 되는데 문자열 '1'을 숫자로 변환한 후 값을 비교true == 'true'//false #불리언 값을 1로 변환화면 1 =='true'가 되는데 문자열 'true'는 숫자로 변환 불가
그리하여 1 == 'true'로 비교되며 false를 반환
null == undefined//true #C++에서 null과 undefiend은 엄연히 다르지만, ==연산자는 true를 반환
===연산자는 타입을 변환하지 않아, ==연산자 방식에 비해 엄격함. 즉 ===연산자는 타입이 다르면 false를 반환
500 === 500// true500 === '500'// falsetrue === 1// falsetrue === 'true'// falsenull === undefined// falseNaN 값은 자기 자신을 포함하여 어떠한 값과도 일치하지 않음. 즉, === 연산자에 NaN 값이 존재하는 경우 항상 false입니다.
정확한 문자열을 비교하기 위해서는 localeCompare 메서드를 사용하는 것을 권장.
문자열은 눈으로 보았을 때, 동일하더라도 인코딩 방식이 다르게 되어있을 수 있기 때문.
출처는 https://developer-talk.tistory.com/184
정적타입(Statically typed) vs 동적타입 (Dynamically typed)
정적타입의 언어는 컴파일 시 변수의 타입이 결정되는 언어를 말함.
그리하여 엔지니어가 변수에 들어갈 값의 형태에 따라 변수의 타입을 직접 명시해줘야함
char name = "blake";
int num = 100;
⭐️정적 타입의 언어는 타입 에러로 인한 이슈를 초기에 발견할 수 있어 타입의 안정성이 높음
또한 컴파일 시에 미리 타입을 결정하기 때문에 구동속도가 빠름
단점으로는 코드 작성 시, 매번 타입을 결정해줘야하는 번거로움이 있음
동적언어는 컴파일 시에 자료형을 정하는게 아닌 런타임 시 결정됨.
장점으로는 런타임까지 타입에 대한 결정을 가지고 갈 수 있어 유연성이 높아짐
또한 컴파일시에 타입을 직접 명시해주기 않아도 되기 때문에 빠른 타이핑이 가능
단점으로는 실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있음
출처: https://devuna.tistory.com/82 [튜나 개발일기:티스토리]
두 타입 모두 자바스크립트에서는 '값이 없음'을 의미함.
그러나 null은 직접적으로 값이 없어라고 말한 상태를 의미하고 undefined는 값이 할당되지 않았음을 의미.
출처 : https://stackabuse.com/javascript-check-if-variable-is-a-undefined-or-null/
기본형 또는 원시형(Primitive type) : 값을 바로 그대로 할당
- Number
- String(문자열)
- Boolean
- null
- undefinded
- Symbol(ES6 부터 추가 됨, 객체 속성을 만드는 데이터 타입)
만약 변수 a를 선언하면 컴퓨터는 우선 메모리 안에 데이터를 담을 공간을 미리 확보함//let a; a = 10;
예를 들어 주소 211번의 공간을 확보했다면 그 다음으로 확보한 주소값을 변수명 a와 매칭시킴
이때 코드를 진행하는 도중에 a에 10을 할당하라는 명령을 만나면 컴퓨터는 변수 a를 찾아서 변수 a와 매칭되는 주소값인
211번을 읽고 그 주소로 이동해서 그 공간에 10을 넣어줌
참조형(Reference Type) : 값이 저장된 주소 값을 할당(참조)
let obj = {
a : 1,
b : 'b'
};
- Object
- Array
- Function RegExp
- Map
- else..
기본형과 마찬가지로 메모리 공간을 확보하고 주소를 변수명과 매칭시키는 과정은 동일함
예를 들어 주소값이 112인데 이제 할당하려고 보니 그 값이 기본형이 아니고 참조형인걸 알아챔
(참조형 데이터들은 property와 data, 즉 key : value로 묶인 쌍들로 이루어져 있음,
Property명은 변수와 비슷한 성질을 지니고 있고, 변수명과 실제 데이터는 주소값을 통하여 연결되어 있음,
이런 경우 우선 각 property 명과 value가 담길 주소를 매칭하기 위해서 새로운 공간을 확보함(예: 주소값 422)
이제 422에 a 프로퍼티에 value가 담길 공간을 확보하고 확보된 주소를 a 프로퍼티와 매칭시킴
주소 422 {
a :@423,
b :@424
}
주소 423에 1이 들어가고
주소 424에 'b'가 들어감
그리고 처음 할당한 주소 112에는 @422를 넣음
결과적으로 참조형 데이터는 ⭐️기본형 데이터들의 집합
참조 : https://velog.io/@mmzgpgp/JavaScript-%EA%B8%B0%EB%B3%B8%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%B0%B8%EC%A1%B0%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0https://velog.io/@mmzgpgp/JavaScript-%EA%B8%B0%EB%B3%B8%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%B0%B8%EC%A1%B0%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0https://velog.io/@mmzgpgp/JavaScript-%EA%B8%B0%EB%B3%B8%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%99%80-%EC%B0%B8%EC%A1%B0%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0
JavaScript 형변환(Type Casting)
자바스크립트는 유연한 언어이기 때문에 자바스크립트 엔진 필요에 따라 묵시적 변환 또는 개발자 의도에 따른 명시적변환을 실행
묵시적 형 변환(Implicit type conversion)
묵시적 변환이란 자바스크립트 엔진이 필요에 따라 자동으로 데이터 타입을 변환시키는 것이다.
1) 산술연산자
더하기(+) 연산자는 숫자보다 문자열이 우선시 되기 때문에, 숫자형이 문자형을 만나면 문자형으로 변환하여 연산됨.
number + number// number
number + string// string
string + string// string
string + boolean// string
number + boolean// number1 + 1;//2100 + “점”;//”100점”
“100” + “점”;//”100점”
“10” + false;//”100"99 + true;//100
다른 연산자(- * / %)는 숫자형이 문자형보다 우선시되기 때문에 더하기와 같은 문자형으로의 변환이 일어나지 않는다.
//다른 연산자(-,*,/,%)
string * number// number
string * string// number
number * number// number
string * boolean//number
number * boolean//number
“2” * false;//02 * true;//2
명시적 형 변환(Explicit Type Conversion)
명시적 변환이란 개발자가 의도를 가지고 데이터 타입을 변환시키는 것.
타입을 변경하는 기본적인 방법은 Object(), Number(), toString(), Boolean() 와 같은 함수를 이용,
new 연산자가 없다면 사용한 함수는 타입을 변환하는 함수로써 사용된다.
let transform = 100;//NumberObject(transform);//100console.log(typeof transform);//Number
toString(transform);//”100"console.log(typeof transform);//StringBoolean(transform);//trueconsole.log(typeof transform);//Bolean
참조 : https://velog.io/@yunsungyang-omc/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%ED%98%95%EB%B3%80%ED%99%98Type-Casting
불변객체(Immutable Object)란?
불변객체는 변하지않는 객체로 객체가 생성된후 내부 상태가 변하지 않는 객체를 의미.
불변객체를 사용하면 아래와 같은 장점이 있다.
1.쓰레드에 안전하기에 멀티 스레드 환경에서 동기화를 고려하지 않아도 됨
2.내부상태가 변경되지 않기에 Map, Set 요소로 사용하기에 적합
3.한 번 메모리에 할당하면 같은 객체를 계속 호출하여도 새롭게 할당하지 않아도 됨. 그리하여
가비지 컬렉터의 성능을 높힐 수 있음.
4.방어적 복사가 필요없음
원시형 타입은 값이 그 값 자체이므로, 값을 바꿀 수 없음. ⇒ 불변하다.
객체는 같은 객체라도 속성 값을 바꿀 수 있기 때문에 불변하지 않음.(가변성을 가진다)
Object.assign(빈 객체, 복사하려는 객체)
var obj1 = { name: 'Nikki' }
var obj2 = Object.assign({}, obj1)
obj2.name = 'Ashley'
// obj1 => {name: 'Nikki'}// obj2 => {name: 'Ashley'}// obj1의 불변성이 유지된다.Object.freeze(불변하게 만드려는 객체)
var obj1 = { name: 'Nikki' }
Object.freeze(obj1)
obj1.name = 'Ashley'
console.log(obj1)
// {name: 'Nikki'} => 속성 값이 변하지 않음const와 freeze의 차이점은 const는 선언된 변수명이 다른 값을 가리키지 못하도록 하는 것,
freeze는 객체내 속성 값을 바꾸지 못하게 하는 역할
출처 : https://serzhul.io/JavaScript/javascript-%EB%B6%88%EB%B3%80%EC%84%B1(immutability)/
원시 값은 변수에 할당하면 변수(메모리 공간)에 실제 값이 저장됨.
객체를 변수에 할당하면 변수(메모리 공간)에 ﹗참조값(메모리주소)이 저장됨.
얕은 복사는 원객체가 하나인 상태에서 참조 값만 복사함
const obj1 = { a: 1, b: 2};
const obj2 = obj1;
console.log( obj1 === obj2 );// true
깊은 복사는 원시 값처럼 완전한 복사본을 만듬
const obj1 = { a:1, b:2 };
const obj2 = { ...obj };
obj2.a = 100;
console.log( obj1 === obj2 )// falseconsole.log( obj1.a )// 1
References
모던 자바스크립트 Deep Dive (Chapter 11)
https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures
스코프는 변수를 참조하는(접근 가능한)유효한 범위를 의미
선언된 위치에 따라 가능한 범위가 결정되며 ⭐️블럭 안의 변수는 블럭 안에서만 유효함
스코프는 이름 충돌을 방지할 수 있고, 블럭 안에 변수는 블럭이 끝나는 순간 메모리에서 제거가 되기에 메모리 절약 가능
{
const a = 'a';
}
console.log(a);
const b = 'b';
// 함수 외부에서는 함수 내부의 변수를 참조 ❌function show() {
const msg = 'Hi there';
console.log(msg);
}
console.log(msg);
// 함수 외부에서는 함수의 매개변수를 참조 ❌function temp(a, b) {
console.log(a, b);
}
console.log(a, b);
호이스팅
자바스크립트 엔진(Interpreter)이 코드를 구동하기 전에 변수,클래스,함수의 선언문을 위로 올리는 것을 의미
여기서 특징이 만약 let a = 10;을 선언하면 호이스팅은 10이라는 값을 제외하고 let a만 최상단으로 올림.
만약 아래와 같이 변수 초기화 전에 출력하면 에러가 발생
console.log(hello)
let hello = 10;
이 말은 변수는 선언까지만 호이스팅이 되고 초기화는 해당 코드 라인에 도달해야만 가능.
이것은 TDZ ( Temporal Dead Zone )라는 것 때문에 발생하는 것임.
출처 : MDN: https://developer.mozilla.org/en-US/docs/Glossary/Scope
출처 : https://dmitripavlutin.com/javascript-variables-and-temporal-dead-zone/
함수 선언식 (Function Declarations)
일반적인 함수 선언 방식
function Hey() {
return 'Hi';
}
Hey();
함수 표현식 (Function Expressions)
자바스크립트 언어의 특징을 활용한 선언 방식
let Hey = function () {
return 'Hi';
}
Hey();
※ ES6에서 추가된 화살표 함수 방식을 정의할 수도 있다.
let funcArrow = (x,y) => (x+y)
코드는 위에서 아래로 실행되는데 코드가 위로 끌어 올려지면 당연히 그 코드를 우선한다.
hooray();
hiho();
function hooray(){
console.log('Yeah');
}
const hiho = function() {
console.log('Oh');
}
//함수 선언문으로 작성했기 때문에 hooray는 실행이 된다.//반면 함수 선언문으로 작성한 함수는 초기화가 되지 않았다는 에러를 볼 수 있다.
함수 선언식은 호이스팅에 영향을 받지만, 함수 표현식은 호이스팅에 영향을 받지 않는다.
var
변수의 중복 선언이 가능.
var 키워드가 붙은 변수는 중복 선언이 가능. 이 기능은 큰 문제가 될 수 있음.
var의 경우에 대표적으로 아래의 4가지 문제가 발생할 수 있음.
// 1. 변수 선언하는 키워드 없이 선언 & 할당이 가능// 선언인지, 재할당인지 구분 어려움// 2. 중복 선언이 가능함// 3. 블록 레벨 스코프 안됨// 4. 함수 레벨 스코프만 지원 됨let, const
1.변수의 중복 선언이 불가능함.
var name = 'Const';
var name = 'Const2';// 아무 일도 일어나지 않았다.let name = 'Const';
let name = 'Const2';// Uncaught SyntaxError: Indentifier 'name' has already been declaredconst name = 'Const';
const name = 'Const2';// Uncaught SyntaxError: Identifier 'name' has already been declared2.블록 레벨 스코프를 사용함
3.let, const 키워드는 선언 생략이 불가능함
함수
자바스크립트에서는 함수도 하나의 타입(datatype).
따라서 함수를 변수에 대입하거나, 함수에 프로퍼티를 지정하는 것도 가능.
또한, 자바스크립트 함수는 다른 함수 내에 중첩되어 정의될 수도 있음.
함수의 정의
자바스크립트에서 함수의 정의는 function 키워드로 시작되며, 다음과 같은 구성요소를 가짐.
1. 함수의 이름
2. 괄호 안에 쉼표(,)로 구분되는 함수의 매개변수(parameter)
3. 중괄호({})로 둘러싸인 자바스크립트 실행문
반환(return)문
자바스크립트에서 함수는 반환(return)문을 포함할 수 있음
이러한 반환문을 통해 호출자는 함수에서 실행된 결과를 전달받을 수 있음.
반환문은 함수의 실행을 중단하고, return 키워드 다음에 명시된 표현식의 값을 호출자에게 반환.
반환문은 배열이나 객체를 포함한 모든 타입의 값을 반환.
출처 : http://www.tcpschool.com/javascript/js_function_basic
실행 컨텍스트 Execution context
실행 컨텍스트는 자바스크립트의 코드가 실행되는 환경을 의미. 2가지로 나뉘며
1.Global Execution Context
->자바스크립트 엔진이 코드를 실행할때 처음으로 생성되는 실행 컨텍스트를 의미
아무런 코드가 없어도 2가지 요소를 가짐(global object, this)
[실행 컨텍스트의 2가지 단계 — 생성, 실행]
1–1 생성단계
global object 생성
this변수 object 생성
변수와 함수를 위한 메모리공간 확보
변수 선언 부분에 undefined(기본값)로 초기화, 선언식 함수를 메모리 공간에 올림
1–2 실행단계
: 실질적으로 자바스크립트 엔진이 코드를 한 줄씩 읽고 실행하는 단계
엔진이 코드를 한 줄씩 실행
실제 값을 메모리 공간에 저장
2.Function Execution Context
->함수가 호출될때 생성되는 컨텍스트
1–1 생성단계
argument object 생성(★글로벌 실행컨텍스트와의 차이점, global object 아님!)
this 변수 object 생성
변수와 함수를 위한 메모리 공간 확보
변수 선언 부분에 undefined로 초기화, 선언식 함수를 메모리 공간에 올림
➡️ 함수 실행컨텍스트는 함수가 호출되면 실행 스택에 쌓였다가, 실행을 마치면 콜스택에서 제거된다.
함수호출 ➡ 새로운 함수 실행 컨텍스트가 콜스택에 쌓임 ➡ 생성단계 ➡ 실행단계 ➡ 콜스택에서 제거
참조 : https://adorable-developlife.tistory.com/29
스코프 체인은 scpoe를 안에서부터 밖으로 차례대로 검색하는 것을 의미.
만약 여러 scope에서 같은 식별자를 선언한 경우에는 무조건 scope chain 상에서
가장 먼저 발견된 식별자에만 접근이 가능하게 됨.
var test = 1;
var a = function() {
var b = function() {
var c = function() {
console.log(test)// undefinedvar test = 3;
};
c();
console.log(test)// 5 // b 스코프 내부에는 test가 없으므로 가까운 a 스코프 값을 참고.
};
var test = 5
b();
console.log(test)// 5 // a 스코프의 가장 가까운 스코프는 자기 자신인 5.
};
a();
console.log(test);// 1 // 전역 스코프에서 가장 가까운 스코프는 자기 자신인 1.
🍇변수 은닉화
앞서 a 스코프에서 전역 변수와 이름이 같은 test를 선언한 바 있음.
이렇게 되면 a 스코프 이하에 있는 스코프들은 전역 변수에 접근할 수 없게 됨.
이러한 기법을 '변수 은닉화'라고 함.