- 표현식과 그 구성 요소인 연산자를 설명.
- 표현식이란 어떤 값으로 평가(evaluate)되는 구절
- 프로그램의 포함된 상수도 단순하지만 표현식. 변수 이름 역시 표현식이며 그 변수에 할당된 값으로 평가.
- 단순한 표현식을 조합해 복잡한 표현식을 만들 때는 대부분 연산자를 사용
4.1 기본 표현식
1.23;
("hello");
/pattern/;
true;
falsenull;
this;
i
undefined
- 식별자를 변수, 상수, 전역 객체의 프로퍼티라고 가정하고 찾지만 없다면 ReferenceError
4.2 객체와 배열 초기화 표현식
[] // 빈 배열
[1+2, 3+4]
- 배열 초기화 표현식 내부의 요소 표현식 역시 배열 초기화 표현식이 될 수 있다.
let matrix = [[1,2,3],[4,5,6],[7,8,9]]
- 배열 초기화 표현식 내의 요소 표현식은 배열 초기화 표현식을 평가할 때마다 평가된다.
- 객체 초기화 표현식은 배열과 비슷하지만 중괄호, 각 하위 표현식은 프로퍼티 이름과 콜론으로 시작한다는 점에서 다르다.
let rectangle = {
upperLeft: { x: 2, y: 2 },
lowerRight: { x: 4, y: 5 },
};
4.3 함수 정의 표현식
- 함수를 정의하면 그 값은 함수다.
- 일반적으로 function 키워드로 시작
let square = function (x) {
return x * x
}
- ES6 이후 부터는 ‘화살표 함수’ 문법으로 사용 가능
4.4 프로퍼티 접근 표현식
- 객체 프로퍼티나 배열 요소의 값으로 평가.
- expression . identifier
- expression [ expression ]
- 위의 두가지 스타일이 있다. 어떤 스타일이든 .이나 [ 앞에 있는 표현식을 먼저 평가. null이나 undefined이면 표현식은 TypeError 일으킨다.
- 프로퍼티 이름에 스페이스나 구두점, 숫자인 경우 대괄호 표기법 사용.
4.4.1 조건부 프로퍼티 접근
-
expression ?. identifier
-
expression ?. [expression ]
-
왼쪽의 표션식이 null이나 undefined로 평가 될때의 에러를 방지할 수 있다. 뒤의 프로퍼티의 접근을 막아 null 또는 undefined로 평가.
-
이런 형태의 프로퍼티 접근 표현식을 “옵션 체인”이라고 부른다.
4.5 호출 표현식
f(0);
a.sort()
- 호출 표현식을 평가할 때는 첫 번째는 함수 표현식을 평가하고, 그 다음으로 함수 인자 표현식을 평가해 인자 값 리스트를 만든다 → 함수 표현식 값이 함수가 아니라면 TypeError
- 인자 값을 함수를 정의할 때 지정된 함수 매개변수(parameter)에 순서대로 할당한 다음 함수 바디 실행.
- 함수가 return 문을 사용해 값을 반환한다면 그 값이 호출 표현식의 값.
- 그렇지 않다면 undefined.
- 호출 표현식 맨 앞에 있는 표현식이 프로퍼티 접근 표현식이라면 이 호출은 메서드 호출이라고 한다.
4.5.1 조건부 호출
- ES2020에서는 () 대신 ?.()로 함수 호출 가능
- 왼쪽 표현식이 null또는 undefined로 평가될때 표현식 전체를 null또는 undefined로 평가
function square(x, log) {
if (log) {
log(x);
}
return x * x;
}
function square(x, log) {
log?.(x);
return x * x;
}
4.6 객체 생성 표현식
- 객체를 생성하고 함수(생성자)를 호출해 객체 프로퍼티를 초기화.
- 객체 생성 표현식은 호출 표현식과 같지만, 그 앞에 new 키워드를 붙인다.
new Object();
new Point(2, 3);
4.7 연산자 개요
- 연산자는 산술, 비교, 논리, 할당 표현식 등에 사용된다.
- 대부분의 연산자는 +나 = 처럼 부호로 표현
- 연산자는 연산자 우선순위가 있다.




4.7.1 피연산자 갯수
- 연산자는 예상하는 피연산자 개수를 기준을 분류가능
- 단항, 2항, 3항 연산자
4.7.2 피연산자와 결과 타입
- 대부분은 피연산자가 특정 타입일 것으로 간주하여 특정 타입의 값을 반환.
- 는 피연산자가 숫자라고 예상하지만 “3” “5”는 유효하고 15를 반환.
- +는 숫자끼리 더하면 숫자, 문자가 포함되면 문자열을 반환한다.
4.7.3 연산자와 부수 효과
- 일부 표현식은 이후의 평가 결과에 영향을 미치는 부수 효과가 있다.
- 할당 연산자가 그 예
4.7.4 연산자 우선순위
- 연산자는 표와 같이 우선순위를 같는다.
- 현실에서 연산자 우선순위가 불확실하다면 괄호를 사용해서 순서를 명시적으로 정하기.
4.7.5 연산자 결합성
- 지수, 단항, 할당, 조건 연산자는 오른쪽에서 왼쪽으로 수행
4.7.6 평가 순서
- 표현식을 왼쪽에서 오른쪽으로 평가한다.
- w = x + y z는 w → x,y,z, 순서로 평가한다음 y z ⇒ x의 값을더한다음 w에 할당
4.8 산술 표현식
- 산술 연산을 비롯한 피연산자의 숫자를 조작하는 연산자에 관한 설명
- 지수, 곱셉, 나눗셈, 뺄셈은 피연산자를 평가해 필요하다면 숫자로 변환한 다음 제곱, 곱, 몫, 나머지, 차이를 계산. 숫자가 아니며 숫자로 변환할 수도 없는 값은 NaN 값으로 변환
4.8.1 + 연산자
- 숫자 피연산자는 더하고, 문자열은 병합
- 연산자의 변환 규칙은 문자열 병합에 우선 순위가 있다.
- 두 피연산자 모두 문자열로 판단할 수 없을 때만 덧셈을 수행.
4.8.2 단항 산술 연산자
증가 ++
let i = 1, j = ++i; // i와 j는 2
let n = 1, m = n++; // n은 2이고 m은 1
- 표현식 x++가 항상 x=x+1과 같지 않다. ++는 절대 문자열을 병합하지 않는다.
- for 루프에서 1증가시키는 목적으로 많이 사용됨
4.8.3 비트 연산자
- 숫자의 이진 표현의 비트를 대상으로 저수준 조작을 수행
- 비트 연산자는 피연산자에 정수 값을 예상하며, 이 값이 64비트 부동 소수점 값이 아니라 32비트 정수인 것처럼 동작.
- 이들 연산자는 필요하다면 피연산자를 숫자로 변환하고, 그 숫자 값에서 소수 부분과 32번째 이후의 비트를 모두 버려서 32비트 정수로 강제 변환 한다.
- 시프트 연산자는 이 피연산자를 부호 없는 32비트 정수로 변환한 다음 다섯 번째를 넘어가는 비트를 모두 버려서 적절한 범위의 숫자로 만든다.
4.9 관계 표현식
- 관계 연산자는 두 값 사이의 관계를 나타내며 false 또는 true를 반환
- 버그 방지를 위해 === 일치 연산자 써야 한다.
4.9.2 비교연산자
- 문자열 비교에서 주의점은 문자열은 16비트 정수의 연속이기에 ASCII 대문자는 ASCII 소문자보다 작다.
- < 연산자는 “ZOO”는 “arrdsf”보다 작다고 판단함.
- 문자열 비교 알고리즘이 필요할 때는 String.localeCompare() 메서드를 고려.
- 또는 toLowerCase(), toUpperCase()
4.9.3 in 연산자
- in 연산자는 왼쪽 피연산자가 문자열, 심벌, 문자열로 변환될 수 있는 값이라고 예상.
- 오른쪽은 객체라고 예상
- 왼쪽 피연산자가 오른쪽 객체의 프로퍼티 이름일 경우 true를 반환
let point = { x: 1, y: 1 };
"x" in point;
"Z" in point;
"toString" in point;
4.9.4 instanceof 연산자
- 왼쪽 피연산자가 객체, 오른쪽 피연산자는 객체의 클래스라고 예쌍.
- 왼쪽에 있는 객체가 오른쪽에 있는 클래스의 인스턴스라면 true, 아니면 false를 반환한다.
let d = new Date()
d instanceof Date // true
d instanceof Object // true
d instanceof Number // false : d는 Number의 객체가 아니다.
- 객체는 모두 Object의 인스턴스.
- 오른쪽 피연산자가 객체의 클래스가 아니라면 TypeError가 발생한다.
- 자바스크립트는 o instanceof f라는 표현식을 평가할 때 먼저 f.prototype을 평가한 후 o의 프로토타입 체인에서 그 값을 찾는다. 찾으면 o는 f의 인스턴스이며 연산자는 true를 반환.
4.10 논리 표현식
- 논리연산자 &&, ||, !는 불 연산응ㄹ 수행한다.
4.10.1 불 AND(&&)
- 불 AND연산을 수행
- 첫 번째 피연산자와 두 번째 피연산자가 모두 true일 때만 true를 반환.
- 둘 중에 하나라도 false면 false를 반환.
- 자바스크립트 값은 모두 true 같은 값 또는 false 같은 값으로 해석 가능
- 이 연산자는 먼저 왼쪽에 있는 첫 번째 피연산자를 평가, 왼쪽 값이 false이면 오른쪽 표현식을 평가하려 하지 않고 왼쪽에 있는 값을 반환한다.
- 반면 왼쪽에 있는 값이 true면 표현식의 전체적인 값은 오른쪽에 있는 값
- 오른쪽에 있는 값이 true 값이면 전체적인 값도 반드시 true 같은 값.
let o = { x: 1 };
let p = null;
o && o.x // 1 = o는 true같은 값이므로 o.x으 ㅣ값을 반환
p && p.x // null : p는 false 같은 값이므로 p.x는 평가하지 않는다.
&&는 오른쪽에 있는 피연산자를 평가할 수도, 그렇지 않을 수도 있다는 점을 이해해야한다.
이런 동작 방식은 단축 평가라고 부르며 코드를 조건부로 실행하려 할 때 사용
if (a === b) stop();
a === b && stop();
4.10.2 불 OR(||)
- OR 연산 수행.
- 둘다 true 같은 값이면 true 같은 값을 반환.
- 이 연산자는 먼저 왼쪽에 있는 첫번째 피연산자를 평가, true 같은 값이면 단축 평가가 일어나 오른쪽 표현식을 평가하지 않고 바로 true 같은 값을 반환
- 반면 첫 번째가 false 같은 값이면 || 연산자는 두 번째 피연산자를 평가하고 그 값을 표현식의 값으로 반환.
이 연산자는 몇 가지 변수 중에서 첫 번째로 등장하는 true 같은 값을 선택하려 할 때 자주 사용.
let max = maxWidth || preferences.maxWidth || 500;
4.10.3 불 Not(!)
- 피연산자의 불값을 부정 할 때 사용.
- !는 항상 true, false를 반환.
- !는 단항연산자이므로 우선순위가 높고 피연산자와 단단히 결합되므로 적절한 괄호가 필요.
!(p && q) === (!p || !q)
!(p || q) === (!p && !q)
4.11 할당 표현식
- JS는 = 연산자를 사용해 변수나 프로퍼티에 값을 할당 한다.
i = j = k = 0
4.11.1 할당과 연산
- JS는 일반적인 = 할당 연산자 외에도 할당 연산자와 다른 연산자를 결합한 단축 표현을 지원
- 예를 들어 +=
4.12 평가 표현식
- JS는 문자열을 JS 소스 코드로 해석하고 평가해서 값을 얻을 수 있다.
eval("3+2")
거의 필요하지 않다 (안쓴다.)
4.12.1 eval()
- 인자 하나 받고 문자열이 아닌 값을 전달하면 그 값을 반환.
4.12.2 전역 eval()
- eval()은 로컬 변수를 엉망으로 만들어 JS 최적화를 어렵게 만든다.
4.13 기타 연산자.
4.13.1 조건 연산자 (?:)
x > 0 ? x : -x;
첫 번째 피연산자를 불로 평가하고 해석, 첫 번째 피연산자의 값이 true 같은 값이면 두 번째 피연산자를 평가하고 그 값을 반환. 그렇지 않다면 세번째 피연산자를 평가하고 그 값을 반환.
greeting = "hello" + (username ? username : "there");
greeting == "hello";
if (username) {
greeting += username;
} else {
greeting += "there";
}
4.13.2 null 병합 연산자(??)
- 왼쪽 피연산자가 null이나 undefined로 평가될 때만 두 번째 피연산자를 반환한다.
- 표현식 a에 부수 효과가 없다면 a ?? b는 다음 코드와 동등하다.
a !== null && a !== undefined ? a : b;
??는 첫 번째 true 같은 값이 아닌 “정의된” 첫 번째 피연산자가 필요할 때 ||를 대체할 수 있는 유용한 연산자
let max = maxWidth || preferences.maxWidth || 500;
이런 관용적 표현에서 문제는 어떤 환경에서는 0이나 빈 문자열, false가 유효한 값임에도 불구하고 모두 false 같은 값으로 취급 한다.
만약 maxWidth가 0이면 그값을 무시된다. 하지만 || 연산자를 ??로 바꾼다면 다음과 같이 0 역시 유효한 값으로 사용될 수 있다.
let max = maxWidth ?? preferences.maxWidth ?? 500;
?? 연산자는 &&나 || 연산자와 비슷하긴 하지만 우선순위 관계가 명확하지 않는다. 그렇기에 괄호를 사용
4.13.3 typeof 연산자
- 이는 단항 연산자이며 피연산자 타입을 가리지 안흔ㄴ다.

typeof는 피연산자의 값이 null일 때 ‘object’를 반환한다. null과 객체를 구별하고 싶다면 직접 테스트 해야한다.
객체 클래스는 모두 뭉뚱그려 “object”로 평가하므로 다른 방법을 통해 구별 해야한다.
4.13.4 delete 연산자
- 피연산자로 지정된객체 프로퍼티나 배열 요소를 삭제하는 단항 연산자.
- 이 연산자는 프로퍼티를 삭제한다는 부수 효과를 목적으로 사용되며 반환되는 값을 기대하지 않는다.
4.13.5 await 연산자.
- await는 비동기 연산을 나타내는 프라미스 객체를 피연산자로 예상하고, 프로그램이 마치 그 비동기 연산이 끝나길 기다리는 것처럼 동작. 하지만 실제로 기다리지는 않고 넘어가며 다른 비동기 동작도 동시에 일어날 수 있따.
4.13.6 void 연산자.
- 단항, void는 피연산자를 평가한 후 그 값을 버리고 udefined를 반환.
- 피연산자의 값이 버려지므로, void 연산자는 피연산자에 부수 효과가 있을 때에만 의미 있다.