연산자(operator)는 표현식을 대상으로 산술, 할당, 비교, 연산등을 수행해 값을 만든다.
산술 연산자(arithmetic operator)는 피연산자을 수학적 계산을 통해 새로운 숫자 값을 만든다. 연산이 불가능할 경우 NaN을 반환한다.
이항 산술 연산자는 2개의 피연산자를 산술 연산하여 숫자 값을 만든다. 단 피연산자의 값을 변경하는 부수 효과(side effect)가 없다.
1 + 2
2 - 1
2 * 1
2 / 1
5 % 2
1개의 피연산자를 산술 연산하여 숫자 값을 만든다.
++ : 증가
-- : 감소
+ : 숫자 타입이 아닌 피연산자를 숫자 타입으로 변환해준다.
- : 양수를 음수로, 음수를 양수로 반전한다.
이항 산술 연산자와는 다르게 피연산자의 값을 변경시킬 수 있다.
let x = 1
x++
console.log(x) // 2
++/--연산자는 위치에 의미가 있다.
let x = 1
let v
v = x++ // 뒤에 연산자
console.log(v,x) // 1 2
v = ++x // 앞에 연산자
console.log(v,x) // 3 3
'+'는 숫자 타입이 아닌 피연산자에 사용하면 숫자 타입으로 변환한다.
불린값은 true는 1 false는 0으로 반환한다.
let num = '1'
console.log(typeof num) // string
console.log(typeof +num) // number
num = true
console.log(typeof +num) // 1
피연산자가 하나라도 문자열인경우 문자열 연결 연산자로 동작한다.
'hi' + 1 // 'hi1'
true + 1 // 2 true는 1 false는 0으로 처리
null + 1 // 1 null은 0으로 처리
위의 불린값과 null은 타입 강제 변환이 되어 의도와 다른 값이 나올 수도 있다.
할당 연산자(assignment operator)는 우항에 있는 피연산자의 평가 결과를 좌항의 변수에 할당한다.
= x = 1
+= x += 1
-= x -= 1
*= x *= 1
/= x /= 1
%= x %= 1
비교 연산자(comparison operator)는 좌항과 우항의 피연산자를 비교 후 그 결과를 불린 값으로 반환한다.
동등 비교 연산자와 일치 비교 연산자는 좌항과 우항의 피연산자를 비교해 불리언 값을 반환한다.
비교하는 엄격성의 정도가 연산자에 따라 다르다.
== 동등 비교 x == y
=== 일치 비교 x === y
!= 부동등 비교 x != y
!== 불일치 비교 x !== y
동등 비교 연산자(==)는 암묵적 타입 변환을 통해 타입을 일치 시킨 후 같은 값인지 비교한다.
의도와 다른 결과가 나올 확률이 높다.
1 == 1 // true
1 == '1' // true
0 == '' // true
일치 비교 연산자(===)를 사용하자. 단 NaN과 -0(음의 0) 주의한다.
1 === '1' // false
NaN === NaN // false
0 === -0 // true
Object.is()???
Object.is 메서드는 일치 비교 연산자와 비슷하나 더 정확한 비교 결과를 반환한다. 음의0이나 NaN이 피연산자로 나올 수 있다면 이 메서드를 사용한다.0 === -0 // true Object.is(0, -0) // false Object.is(NaN, NaN) // true
피연산자의 크기를 비교하여 불린 값을 반환한다.
> x > y
>= x >= y
삼항 조건 연산자(ternary operator)는 조건식의 평가에 따라 반환한다.
let a = 5
let result = a >= 5 ? 10 : 20 // 10
변수선언 = 비교연산자 ? true일때 값 : false일때 값
위의 식은 true였으므로 result는 10을 할당 받게된다. if...else문과 유사한 처리 결과인데 삼항 연산자 표현식은 값처럼 사용 가능하지만 if문은 값처럼 사용 할 수 없다.
논리연산자(logical operator)는 우항과 좌항의 피연산자를 논리 연산한다.
|| 논리합(OR) +덧셈이라 생각하면 편하다 둘중 하나라도 true면 true를 출력
&& 논리곱(AND) *곱셈 둘중 하나라도 true가 아니면 false를 출력
|| / &&는 평가 결과가 불린값이 아닐수 도 있다.
! 부정(NOT) !0 // true가 된다 암묵적 타입변환되니 조심
드모르간의 법칙???
논리 연산자로 구성된 표현식은 가독성이 좋지 않다. 좀 더 가독성 좋은 표현식으로 생각해본다.!(x || y) === (!x && !y) // true !(x && y) === (!x || !y) // true
왼쪽 피연산자부터 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환한다.
let x, y;
x = 1, y = 2; // 2
소괄호()로 피연산자를 감싸는 그룹 연산자는 자신의 표현식을 가장 먼저 평가한다.
2 * 3 + 4 // 10
2 * (3 + 4) // 14 산술의 우선순위가 달라졌다.
피연산자의 데이터 타입을 문자열로 반환한다.
string, number, boolean, undefined, symbol, object, function 중 하나를 반환한다.
typeof '' // "string"
typeof 1 // "number"
typeof [] // "object"
typeof null // "object"
null 값과 배열도 object를 반환하니 주의해야 한다.
좌항의 피연산자를 밑(base)으로, 우항의 피연산자를 지수로 거듭 제곱하여 숫자 값을 반환한다.
2 ** 2 // 4
2 ** 2.5 // 5.65685424949238
2 ** 0 // 1
2 ** -2 // 0.25
(-5) ** 2 // 25 음수를 base로 사용하려면 소괄호로 묶어야 한다.
let num = 2
num **= 2 // 4 할당 연산자와 함께 사용할 수 있다.
2 * 3 ** 3 // 54 이항 연산자중 지수 연산자가 우선순위가 가장 높다
지수 연산자 전에는 Math.pow 메서드를 사용했다
Math.pow(2,2.5) // 5.65685424949238
객체를 가리키기 기대하는 변수가 null이나 undefined인지 확인할때 쓴다.
좌항의 피연산자가 null 또는 undefined인경우 undefined를 반환하고 아니면 우항의 프로퍼티 참조를 이어간다.
let str = 'hi'
let result = str?.length
console.log(result) // 2 str 변수에 'hi'문자열이 있기에 2를 반환한다
let non = null
result = non?.length
console.log(result) // undefined
좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고 아니면 좌항의 피연산자를 반환한다.
3항 연산자에서 많이 본것 같다.
let non = null ?? 'hi'
console.log(non) // 'hi'
non = '' ?? 'hi'
console.log(non) // '' 좌항이 falsy한 값이여도 null 또는 undefined가 아니면 죄항 반환
이전에는 || 연산자를 사용한 단축 평가를 통해 변수의 값을 정했다.
좌항의 피연산자가 falsy한 값이면 우항의 피연산자를 반환한다. falsy한 값이라 의도대로 움직이지 않을 수 있다
let non = '' || 'hi' // 좌항에 ''공백을 넣었다
console.log(non) // 'hi'
나중에 배우게 될 객체의 프로퍼티를 삭제하는 연산자다.
밑에 예제를 확인한다.
let person = { // 객체다
a : 'hi'
}
person.b = 1 // 프로퍼티 동적 생성
console.log(person) // {a: 'hi', b: 1} 객체안에 b라는 키에 1이라는 값을 추가했다.
delete person.b
console.log(person) // {a: 'hi'} b 프로퍼티가 삭제된걸 확인할 수 있다.
delete person.c // 없는 프로퍼티를 삭제하려해도 오류는 없다
일반 함수와 생성자 함수는 큰 차이는 없다. 하지만 new 연산자와 함께 함수를 호출하면 생성자 함수로 동작한다. 함수 객체의 내부 메서드인 [call]이 아니라 [Construct]가 호출된다.
// 두개의 파라미터를 받아 합 연산을 해주는 일반 함수, 생성자 함수로 정의되지 않았다.
function fun(x, y) {
return x + y
}
let result = new fun(1,2)
console.log(result) // {} 함수가 객체를 반환하지 않아 반환문이 무시된다.
// 객체를 반환하는 일반 함수
function fun(x, y) {
return {x , y}
}
let result = new fun(1,2)
console.log(result) // {x: 1, y: 2}
반대로 new 연산자 없는 생성자 함수는 일반 함수로 호출된다.
function Fun(x) {
this.x = x
this.sum = function () {
return 5 + this.x
}
}
const fun = Fun(2)
console.log(fun) // undefined
console.log(x) // 2 일반 함수 내부의 this는 전역 객체 window다.
console.log(sum()) // 7
new 연산자를 사용해 생성자 함수를 호출했다.
function Fun(x) {
this.x = x
this.sum = function () {
return 5 + this.x
}
}
const fun = new Fun(2) // new 연산자를 통해 호출했다
console.log(x) // 레퍼런스 오류
console.log(fun.sum()) // 7
Fun 함수를 new 연산자로 호출하면 함수 내부에서 사용한 this는 fun 생성자 함수가 생성할 인스턴스를 의미한다.
이항 연산자로 좌변에 객체를 가리키는 식별자, 우변에 생성자 함수를 가리키는 식별자를 피연산자로 받는다. 우변의 생성자 함수의 prototype에 바인딩된 객체가 좌변의 객체의 프로토타입 체인 상에 존재하면 true로 아니면 false로 평가된다.
function Ins(x) {
this.x = x
}
const y = new Ins(5)
console.log(y instanceof Ins) // true
console.log(y instanceof Object) // true

개발자 콘솔로 확인해보면 왜 true 결과값이 나왔는지 알 수 있다.
객체 내에 프로퍼티가 존재하는지를 불린값으로 평가한다.
//객체 생성
let obj = {a : 1, b : 2}
console.log('a' in obj) // true
console.log('c' in obj) // false
연산자에는 우선순위가 있어 여러 연산자로 이뤄진 문이 있다면 먼저 실행되는 순서가 있다.
1. ()
2. new(매개변수 존재),[](프로퍼티 접근시),()(함수 호출), ?.(옵셔널 체이닝 연산자)
3. new(매개변수 미존재)
4. x++, x--
5. !x, +x, -x, ++x, --x, typeof, delete
6. **(이항 연산자중 우선순위가 가장 높다)
7. *, /, %
8. +, -
9. <, <=, >, >=, in, instanceof
10. ==, !=, ===, !==
11. ??(null 병합 연산자)
12. &&
13. ||
14. ? ... : ... (3항 연산자)
15. 할당 연산자(=, +=, -=, ...)
16. ,
생각보다 연산자의 우선순위가 종류가 있기에 그룹 연산자를 활용한다.