책 읽기자바스크립트 딥다이브
자바스크립트 딥다이브 2
연산자
- 증가/감소(++/--) 연산자는 피연산자의 값을 변경하는 부수 효과가 있다.
var x = 1;
// ++ 연산자는 피연산자의 값을 변경하는 암묵적 할당이 이뤄진다.
x++;
console.log(x); // 2
// -- 연산자는 피연산자의 값을 변경하는 암묵적 할당이 이뤄진다.
x--;
console.log(x); // 1증가/감소 연산자
- 피연산자 앞에 위치한 전위 증가/감소 연산자는 먼저 피연산자의 값을 증가/감소 시킨 후 다른 연산을 수행한다.
- 피연산자 뒤에 위치한 후위 증가/감소 연산자는 먼저 다른 연산을 수행한 후 피연산자의 값을 증가/감소 시킨다.
var x = 5,
result;
// 선할당 후증가(postfix increment operator)
result = x++;
console.log(result, x); // 5 6
// 선증가 후 할당 (prefix increment operator)
result = ++x;
console.log(result, x); // 7 7
// 선할당 후감소(postfix decrement operator)
result = x--;
console.log(result, x); // 7 6
// 선감소 후할당(prefix decrement operator)
result = --x;
console.log(result, x); // 5 5문자열 연결 연산자
+연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작한다.1 + true를 연산하면 자바스크립트 엔진은 암묵적으로 불리언 타입의 값인 true를 숫자 타입인 1로 타입을 강제로 변환한 후 연산을 수행한다.- 이를 암묵적 타입변환 또는 타입 강제변환 이라고 한다.
동등/일치 비교 연산자
- 동등 비교 연산자(==)는 느슨한 비교를 하지만 일치 비교 연산자(===)는 엄격한 비교를 한다.
- 동등 비교 연산자(==)는 좌항과 우항의 피연산자를 비교할 때 먼저 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교한다.
- 일치 비교 연산자(===)는 좌항과 우항의 피연산자가 타입도 같고 값도 같은 경우에 한하여 true를 반환한다.
주의 사항
// NaN은 자신과 일치하지 않는 유일한 값이다.
NaN === NaN; // false
// 숫자가 NaN인지 조사하려면 빌트인 함수 Number.isNaN을 사용한다.
Number.isNaN(NaN); // true
Number.isNaN(10); // false
Number.isNaN(1 + undefined); // true// 양의 0과 음의 0의 비교 (일치 비교/동등 비교 모두 true)
0 === -0; // true
0 == -0; // truetypeof 연산자
| 타입 | 비고 | |
|---|---|---|
typeof '' | string | |
typeof 1 | number | |
typeof NaN | number | number 타입 주의 |
typeof true | boolean | |
typeof undefined | undefined | |
typeof null | object | object 타입 주의 |
typeof Symbol() | symbol | |
typeof [] | object | |
typeof {} | object | |
typeof new Date() | object | |
typeof /abc/gi | object | |
typeof function() {} | function |
typeof 연산자
- typeof 연산자로
null값을 연산해 보면null이 아닌object를 반환한다는 데 주의하자.- 이는 자바스크립트의 첫 버전의 버그이다.
- 값이
null타입인지 확인할 때는 일치 연산자 (===)를 사용하자.
제어문
블록문
- 블록문(block statement/compound statement)은 0개 이상의 중괄호로 묶은 것으로, 코드 블록 또는 블록이라고 부르기도 한다.
// 블록문
{
var foo = 10;
}
// 제어문
var x = 1;
if (x < 10) {
x++;
}
// 함수 선언문
function sum(a, b) {
return a + b;
}조건문
- if 문의 조건식이 불리언 값이 아닌 값으로 평가되면 자바스크립트 엔진에 의해 암묵적으로 불리언 값으로 강제 변환되어 실행할 코드 블록을 결정한다.
var x = 2;
var result;
// 2 % 2는 0이므로 조건식은 false이다.
if (x % 2) {
result = "홀수";
} else {
result = "짝수";
}
console.log(result); // 짝수타입 변환과 단축 평가
- 개발자가 의도적으로 값의 타입을 변환하는 것을 명시적 타입 변환 또는 타입 캐스팅이라 한다.
- 자바스크립트 엔진에 의해 표현식을 평가하는 도중 암묵적으로 타입이 자동으로 변환되기도 한다.
- 이를 암묵적 타입 변환 또는 타입 강제 변환이라 한다.
문자열 타입으로 변환
- 문자열 연결 연산자 표현식을 평가하기 위해 문자열 연결 연산자의 피연산자 중에서 문자열 타입이 아닌 피연산자를 문자열 타입으로 암묵적 타입 변환한다.
1 + "2"; // "12"숫자 타입으로 변환
- 산술 연산자 표현식을 평가하기 위해 산술 연산자의 피연산자 중에서 숫자 타입이 아닌 피연산자를 숫자 타입으로 암묵적 타입 변환한다.
- 이때 피연산자를 숫자 타입으로 변환할 수 없는 경우는 평가 결과가 NaN이다.
10 - "2"; // 8
10 * "2"; // 20
10 / "one"; // NaN- 비교 연산자는 피연산자의 크기를 비교하므로 모든 피연산자는 코드의 문맥상 모두 숫자 타입이어야 한다.
- 자바스크립트 엔진은 비교 연산자 표현식을 평가하기 위해 비교 연산자의 피연산자 중에서 숫자 타입이 아닌 피연산자를 숫자 타입으로 암묵적 타입 변환한다.
"10" > 2; // true+ 단항 연산자
- + 단항 연산자는 피연산자가 숫자 타입의 값이 아니면 숫자 타입의 값으로 암묵적 타입 변환을 수행한다.
// 문자열 타입
+""; // 0
+"10"; // 10
+"one"; // NaN
// 불리언 타입
+true; // 1
+false; // 0
// null 타입
+null; // 0
// undefined 타입
+undefined; // NaN
// 심벌 타입
+Symbol(); // TypeError: Cannot convert a Symbol value to a number
// 객체 타입
+{}; // NaN
+[]; // 0
+[10, 20]; // NaN
+function () {}; // NaN주의 사항
- 빈 문자열, 빈 배열, null, false는 0으로, true는 1로 변환된다.
- 객체와 빈 배열이 아닌 배열, undefined는 변환이 되지 않아 NaN이 된다는 것에 주의해야한다.
객체란?
- 자바스크립트는 객체 기반의 프로그래밍 언어이며, 자바스크립트를 구성하는 거의 "모든 것"이 객체다.
- 원시 값을 제외한 나머지 값(함수, 배열 정규 표현식 등)은 모두 객체다.
- 원시 타입의 값은 변경 불가능한 값이지만 객체 타입의 값은 변경 가능한 값이다.
- 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환한다.
- ReferenceError가 발생하지 않는데 주의하자.
- delete 연산자는 객체의 프로퍼티를 삭제한다.
- 프로퍼티 삭제 후 객체에 삭제한 프로퍼티가 존재하지 않는다면 프로퍼티 값은 undefined가 된다.
- 존재하지 않는 프로퍼티를 삭제하려고 하면 에러가 발생하지 않는다는 것에 주의하자.
원시 값과 객체의 비교
- 원시 값은 변경 불가능한 값이며 객체는 변경 가능한 값이다.
- 원시 값은 읽기 전용 값으로서 변경할 수 없다.
- 새로운 원시 값을 재할당하면 메모리 공산에 저장되어 있는 값을 변경하는 것이 아니라 새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장한 후 이 공간을 가리킨다. (변수가 참조하던 메모리 공간의 주소가 바뀐다.)
- 값의 이러한 특성을 불변성이라 한다.
- 변수에 원시 값을 갖는 변수를 할당하면 원시 값이 복사되어 전달된다.
- 이를 값에 의한 전달이라 한다.
- 각 변수의 값은 같지만 다른 메모리 공간에 저장된 별개의 값이 된다.
- A 변수의 값을 B에게 할당하고 B의 값을 바꾸더라도 A의 값은 변경되지 않는다.
- 파이썬의 경우 두 변수가 같은 원시값을 참조하다가 어느 한쪽의 값이 바뀌면 새로운 메모리 공간에 재할당된 값을 저장하도록 동작할 수도 있다.
- 식별자는 값이 아니라 메모리 주소를 기억하고 있다. (메모리 주소를 통해 메모리 공간에 접근하면 값을 참조할 수 있다.)
- 객체를 변수에 할당하면 변수에는 참조 값이 저장된다.
- 이를 참조에 의한 전달이라 한다.
- 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다.
- 메모리를 효율적으로 사용하고 객체를 복사해 생성하는 비용을 절약해 성능을 향상시키기 위해 변경이 가능한 값으로 설계되어 있다.
- 단점으로 여러개의 식별자가 하나의 객체를 공유할 수 있다.
- 식별자에 할당된 객체를 다른 변수에 복사(할당)하면 메모리 주소는 다르지만 동일한 참조 값을 갖는다.
- 원본 또는 사본 중 어느 한쪽에서 객체를 변경하면 서로 영향을 주고 받는다.
함수란?
- 함수는 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.
- 함수 내부로 입력을 전달받는 변수를 매개변수(parameter), 입력을 인수(argument), 출력을 반환값(return value)이라 한다.
함수의 정의 방식
function add(x, y) {
return x + y;
}- 함수 선언문은 함수 이름을 생략할 수 없다.
- 함수 선언문 이전에 호출할 수 있다.
const add = function (x, y) {
return x + y;
};- 함수 표현식은 함수 이름을 생략할 수 있다. (이를 익명 함수라 한다.)
- 함수 표현식 이전에 호출할 수 없다.
const add = new Function("x", "y", "return x + y");- Function 생성자 함수는 함수 선언문이나 함수 표현식으로 정의한 함수와 다르게 동작한다.
- 클로저를 생성하지 않는 등의 차이가 있다.
const add = (x, y) => x + y;- 기존 함수와 this 바인딩 방식이 다르며 prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다.
함수 호출
매개변수와 인수
function add(x, y) {
return x + y;
}
// 함수 호출
// 인수 1과 2가 매개변수 x와 y에 순서대로 할당되고 함수 몸체의 문들이 실행된다.
const result = add(1, 2);- 함수 호출 시 매개변수가 생성되어 undefined로 초기화된 후, 인수가 할당된다.
- 함수를 호출할 때 매개변수의 개수만큼 인수를 전달하는 것이 일반적이지만 그렇지 않은 경우에도 에러가 발생하지는 않는다.
- 인수가 부족할 경우 매개변수에는 undefined가 할당된다.
- 함수의 매개변수는 코드를 이해하는 데 방해되는 요소이므로 이상적인 매개변수 개수는 0개이다.
- 매개변수가 많다는 것은 함수가 여러가지 일을 한다는 증거이므로 바람직하지 않다.
- 이상적인 함수는 한 가지 일만 해야하며 가급적 작게 만들어야 한다.
- 매개변수가 3개 이상을 넘어가게 되면 객체 형태로 인수를 전달하는 것이 좋다.
반환문
function multiply(x, y) {
return x * y;
console.log("실행되지 않는다.");
}
multiply(3, 5); // 15- 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다. 따라서 반환문 이후에 다른 문이 존재하면 그 문은 실행되지 않고 무시된다.
return키워드 뒤에 반환값으로 사용할 표현식을 명시적으로 지정하지 않으면 undefined가 반환된다.
다양한 함수의 형태
즉시 실행 함수
함수 선언문이나 함수 표현식으로 정의되지 않은 이름 없는 함수를 즉시 실행할 수 있다.
(function () {
var a = 3;
var b = 5;
return a * b;
})();- 즉시 실행 함수는 함수 이름이 없는 익명 함수를 사용하는 것이 일반적이다.
- 그룹 연산자
(...)내의 기명 함수는 함수 선언문이 아니라 함수 리터럴로 평가되며 함수 이름은 함수 몸체에서만 참조할 수 있는 식별자 이므로 즉시 실행 함수를 다시 호출할 수 없다.
재귀 함수
함수가 자기 자신을 호출하는 것을 재귀 호출이라 한다. 재귀 함수는 자기 자신을 호출하는 행위, 즉 재귀 호출을 수행하는 함수를 말한다.
- 재귀 함수 내에는 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 한다.
- 탈출 조건을 만들지 않으면 함수가 무한히 재귀 호출을 반복하여 스택 오버플로우를 발생시키고 프로그램이 종료된다.
function factorial(n) {
if (n <= 1) return 1;
}중첩 함수
함수 내부에 정의된 함수를 중첩 함수(nested function)라 한다.
- 함수 내부에 정의된 함수를 중첩 함수 또는 내부 함수라 한다.
- 중첩 함수는 외부 함수 내부에서만 호출할 수 있고 일반적으로 외부 함수를 돕는 헬퍼 함수 역할을 한다.
Edit on GitHub
Last updated on