인터프리터에 의해서 동작하는 언어인 스크립트 언어이다.
HTML: 웹페이지의 구조
CSS: 웹페이지의 디자인
JavaScript: 웹페이지의 기능
Boolean 타입
Null 타입
Undefined 타입
Number 타입
BigInt 타입
String 타입
Symbol 타입
var i; // 선언, "undefined"가 저장됨
var sum = 0; // 선언과 초기화
var i, sum; // 한 번에 여러 개의 변수를 함께 선언할 수 있음
var i=0, sum=10, message=”Hello”; // 선언과 초기화를 동시에 해줄 수 있음
name = "javascript"; // 선언되지 않은 변수는 전역 변수가 됨
function hello() {
// ...
}
가장 대중적인 방법이다. 함수의 이름이 hello가 된다. 이미 여러차례 싸질러 놨듯, 호이스팅 되기 때문에 이 함수는 어느 스코프에서든 호출 할 수 있는 함수가 된다.
var hello = function () {
//...
}
이름이 없는 함수를 변수에 담은 방식이다. 이름이 없는 함수긴 한데, 자바스크립트 엔진이 이름을 변수명으로 추정하여 넣는다.
var hello = function () {
//...
}
hello.name
// > "hello"
hello
// > ƒ () {
// //...
// }
변수 할당은 호이스팅 되지 않으므로, 할당 된 이후에만 실행 가능하다.
var hello = () => {
//...
}
그리고 요즘들어 많이 쓰이고 있는 화살표 함수다. 몇가지 다른게 있다면
var hello = function originalName() {
// ...
}
2와 거의 동일하다. 다른 점은 함수 이름이 명확하게 선언되어 있으므로 JS 엔진에 의해 추론되지 않는 다는 것이다.
var hello = (function () {
//...
})()
즉시 실행 함수로, 클로져를 활용할 수 있다. 내부 함수는 변수나 다른 함수등을 쓸 수 있지만,이 함수 밖에서는 완전히 캡슐화되어 접근 할 수 없다. 가장 흔해 빠진 예제 중 하나로는 카운터가 있다.
var myCounter = (function (initialValue = 0) {
let count = initialValue
return function () {
count++
return count
}
})(1)
myCounter() // 2
myCounter() // 3
myCounter() // 4
외부 함수에서 넘겨준 1을 가지고, 내부에서 처리를 하여 리턴하고 있다.
var hello = new Function()
아마도 이런식으로 함수를 쓸일은 거의 없을 것이다.
const adder = new Function('a', 'b', 'return a + b')
adder(2, 6)
// 8
이는 eval()을 사용하는 것과 같기 때문에 굉장히 위험하다. 그리고 이 생성자는 전역 범위로 한정된 함수만 생성할 수 있다.
Scope를 우리말로 번역하면 ‘범위’라는 뜻을 가지고 있습니다. 즉, 스코프(Scope)란 ‘변수에 접근할 수 있는 범위’라고 할 수 있습니다.
- 전역 스코프
코드 어디에서든지 참조할 수 있다.- 지역 스코프
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서 참조할 수 있다.
모든 변수는 스코프를 갖는다. 변수의 관점에서 스코프를 구분하면 다음과 같이 2가지로 나눌 수 있다.
- 전역 변수 (Global variable)
전역에서 선언된 변수이며 어디에든 참조할 수 있다.- 지역 변수 (Local variable)
지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.
변수는 선언 위치(전역 또는 지역)에 의해 스코프를 가지게 된다. 즉, 전역에서 선언된 변수는 전역 스코프를 갖는 전역 변수이고, 지역(자바스크립트의 경우 함수 내부)에서 선언된 변수는 지역 스코프를 갖는 지역 변수가 된다.
전역 스코프를 갖는 전역 변수는 전역(코드 어디서든지)에서 참조할 수 있다. 지역(함수 내부)에서 선언된 지역 변수는 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.
var let const
var : 변수 재선언 가능
const, let : 변수 재선언 불가능
const : 변수 재할당 불가능 (상수)
let : 변수 재할당 가능
var : functional-scope 로 호이스팅됨
const, let : block-scope 로 호이스팅됨
console.log(a)
var a = "hi"
출력 : undefined
console.log(b)
const b = "hi"
출력 : 에러!
즉, let const는 변수를 선언과 초기화 후, 참조해야한다.
일급객체(First-class Object)란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.
1급 객체의 세가지 조건
- 변수나 데이터에 할당 할 수 있어야 한다.
- 객체의 인자로 넘길 수 있어야 한다.
- 객체의 리턴값으로 리턴 할 수 있어야 한다.
위에 대한 조건으로 인해 알 수 있는 것은 함수를 데이터(string, number, boolean, array, object) 다루 듯이 다룰 수 있다는 점이다.
JAVA에서는 위의 조건에 해당되지 않습니다. 하지만 java의 Lambda는 메서드가 1개만 존재하는 인터페이스/클래스를 통해, 마치 함수를 전달하는 것처럼 여겨서, 함수를 1급 객체로 취급하지 않는 java의 단점을 어느정도 해결한 것이라 볼수 있습니다.
const a = () => {
doSomething();
}
데이터를 다룬다는건 변수에 할당이 가능하다는건데, 위의 정의에 의해서 함수 역시 변수에 할당 가능하다.
자바스크립트에서는 함수가 일급객체이다.
파라미터로 함수를 전달하는 함수
콜백함수(Callback Function)란 파라미터로 함수를 전달받아, 함수의 내부에서 실행하는 함수이다.
let number = [1, 2, 3, 4, 5];
number.forEach(x => {
console.log(x * 2);
});
<output>
2
4
6
8
10
콜백함수는 이미 우리의 코드 속에서 자주 사용되고 있다.
예를 들어, forEach 함수의 경우 함수 안에 익명의 함수를 넣어서 forEach 문을 동작시킨다.
전역객체이며 JavaScript의 최상위객체이기도 합니다. DOM, BOM, JavaScript 모두 window 객체의 프로퍼티가 됩니다.

- DOM(Document Object Model) : 문서 객체 모델 - HTML 파일인 웹 문서를 브라우저가 렌더링하려면 브라우저가 이해할 수 있는 구조로 메모리에 올려야합니다. 그것을 구조화하여 표현한 것을 DOM tree, 이런 전체적인 컨셉, 모델을 DOM이라고 합니다.
- BOM(Browser Object Model) : 브라우저 객체 모델 - DOM과 달리 W3C의 표준 객체 모델은 아니지만 웹 브라우저와 관련된 객체의 집합으로써 JavaScript가 웹 브라우저의 기능적인 요소들을 직접 제어하고 관리할 방법을 제공해 줍니다.
자바스크립트에서 소수점 숫자 연산을 하면, 생각지도 못한 오류가 발생한다. 아래처럼 콘솔창에 1.1 + 1.3를 입력하면, 2.4이 아니라 2.40000000000000004 가 나오는 걸 확인해볼 수 있다. 이렇게 소수점 계산 오류가 발생하는 이유와 어떤 방법으로 해결할 수 있는지에 대해 알아보려고 한다. Javascript를 다루다보면 한번쯤은 마주칠 수 있는 오류이기 때문에 나중에 또 당황하지 않도록 기억하고 넘어가자! (Javascript에서만 있는 오류는 아님)
원인
왜 이런 오류가 생기는걸까? 우리는 보통 계산을 할 때 '10진법'을 사용하지만, 우리와 다르게 컴퓨터는 계산을 할 때 0과 1만 사용하는 '2진법'을 사용한다. 그래서 10진법을 2진법으로 바꾸는 변환과정이 필요한데, 소수 중 일부는 이 과정에서 무한소수가 되어버린다. 하지만 컴퓨터 메모리에는 한계가 있어서 무한 소수를 다 담지 못하고 중간에 잘라서 유한 소수로 저장해버린다. 바로 이 과정에서 미세한 오차가 발생하는 것이다.
얕은 복사는 객체의 참조값(주소 값)을 복사하고, 깊은 복사는 객체의 실제 값을 복사합니다.
const obj1 = { a: 1, b: 2};
const obj2 = obj1;
console.log( obj1 === obj2 ); // true
위의 예시처럼 객체를 직접 대입하는 경우 참조에 의한 할당이 이루어지므로 둘은 같은 데이터(주소)를 가지고 있다.
이것이 얕은 복사이다.
const obj1 = { a:1, b:2 };
const obj2 = obj1;
obj2.a = 100;
console.log( obj1.a ); // 100
위 두 객체는 같은 데이터(주소)를 가지고 있고, 그래서 같은 주소를 참조하고 있다.
때문에 obj2의 property를 수정하고, obj1를 출력해도 obj2 값과 동일하다.
깊은 복사
Object.assign() 메소드를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
Object.assign() 메소드를 통해 첫 번째 인자로 빈 { } 객체를, 두 번째 인자로 obj1 넣고 obj2 에 할당하였다.
이제 obj1과 obj2는 다른 주소를 갖게되었다. (그러나 딱, 1 depth 까지만)