자바스크립트 완벽가이드 4장 (표현식과 연산자)

표현식(expression)은 자바스크립트 인터프리터가 값으로 평가하는 자바스크립트 구문이다.

4.1 기본 표현식

가장 간단한 형태의 표현식은 ‘기본 표현식’으로, 다른 표현식을 포함하지 않은 독립적 표현식이다. 자바스크립트에서 기본 표현식은 상수나 리터럴 값, 특정 키워드들 그리고 변수 참조를 말한다.

this는 상수가 아니고 프로그램 안에서 위치에 따라 각기 다른 값으로 평가된다. this 키워드는 객체 지향 프로그래밍에서 주로 사용된다. 메서드의 본문 안에서 this는 메서드를 호출한 객체로 평가된다. 자바스크립트에서는 프로그램 안에 존재하는 각 식별자들을 일단 변수라고 가정하고 값을 살펴보는데 해당 식별자를 이름으로 하는 변수가 없다면, 해당 표현식은 undefined 값으로 평가된다. 하지만 ECMAScript 5의 strict 에서는 존재하지 않는 변수를 평가하려고 하면 ReferenceError 예외가 발생한다.


4.2 객체와 배열의 초기화 표현식

객체와 배열 초기화 표현식은 새로 생성된 객체나 배열을 값으로 하는 표현식이다. 일반 리터럴과는 달리, 이들은 기본 표현식이 아니다. 이들 리터럴은 프로퍼티와 원소의 값을 지정하는 수많은 하위 표현식을 포함할 수 있기 때문이다.


4.4 프로퍼티 접근 표현식

두 프로퍼티 접근 표현식 모두 점(.)이나 대괄호([) 왼쪽 표현식이 먼저 평가된다. 만약 평가된 값이 null이나 undefined이면 이들 값은 프로퍼티를 갖지 않기 때문에 표현식은 TypeError 예외를 발생시킨다. 만약 값이 객체(또는 배열)가 아니면 객체로 변환된다. 객체에 해당 프로퍼티가 존재하지 않으면, 프로퍼티 접근 표현식의 값은 undefined가 된다.

‘. 식별자’ 문법이 두 방법 중 좀 더 간단하지만 접근하려는 프로퍼티 이름이 ‘합법적’ 식별자일 때만 사용 가능하고, 프로그램을 작성할 때 그 식별자를 미리 알고 있어야 한다. 만약 프로퍼티 이름이 예약어이거나, 구두점 문자나 공백을 포함, 숫자일 때는 반드시 대괄호를 사용해야 한다. 대괄호는 프로퍼티 이름이 고정되어 있지 않고, 그 이름 자체가 어떤 연산의 결과인 경우에도 사용할 수 있다.


4.5 호출 표현식

값을 반환하기 위해 return문을 사용하면, 그 값이 결국 호출 표현식의 값이 된다. 함수가 값을 반환하지 않는다면, 함수 표현식의 값은 undefined가 된다.

모든 호출 표현식은 한 쌍의 괄호 ()와, 괄호 앞에 오는 표현식으로 이뤄진다. 만약 그 표현식이 프로퍼티 접근 표현식이면, 호출 표현식은 메서드 호출이 된다. 메서드가 호출되면 함수의 몸체가 실행되는 동안 프로퍼티 접근 표현식이 가리키는 객체나 배열이 모두 this의 값이 된다.

메서드 호출이 아닌 호출 표현식은 보통 전역객체를 this 키워드의 값으로 사용한다. 하지만 ECMAScript 5에서는 메서드 호출이 아닌 호출 표현식을 ‘엄격모드’에서 사용할 경우, 전역 객체 대신 undefined가 this의 값이 된다.’


4.6 객체 생성 표현식

객체 생성 표현식은 새 객체를 생성하고 생성자라고 부르는 함수를 호출해 객체에 속한 프로퍼티들을 초기화한다. 객체 생성 표현식이 평가될 때, 자바스크립트 인터프리터는 먼저 새로운 빈 객체를 생성한다. 이때 생성된 객체는 객체 초기자 {}에 의해 생성되는 객체와 동일하다. 다음으로, 주어진 인자들과 함께 생성자를 호출하는데, 이때 방금 생성된 새 객체를 this 키워드의 값으로 설정하여 전달한다. 생성자 함수는 이 this 키워드를 사용해 새로 생성된 객체의 프로퍼티들을 초기화한다.


4.8 산술 표현식

수로 변환 불가능한 피연산자는 NaN 값으로 변환되며, 피연산자중 하나라도 NaN일 경우에는 연산 결과도 NaN이다.

/ 연산자는 첫 번째 피연산자를 두 번째 피연산자로 나눈다. 정수를 정수로 나누면 계산 값이 당연히 정수가 되리라고 예상하겠지만, 자바스크립트에서 모든 숫자는 부동소숫점 숫자로 취급된다. 따라서 모든 나눗셈 연산의 결과 또한 부동소숫점 숫자 값이 된다. 예를 들어 5/2는 2가 아니라 2.5로 평가된다. 값을 0으로 나누면 양의 무한도 또는 음의 무한대 값이 되고, 0/0의 값은 NaN로 평가된다.

% 연산자 결과의 부호는 첫 번째 피연산자의 부호와 동일하다.

4.8.1 덧셈 연산자 +

1
2
3
4
5
6
7
1 + 2                   // => 3: 덧셈
"1" + "2" // => '12': 이어붙이기
"1" + 2 // => '12': 숫자를 문자열로 바꾼 후 이어붙이기
1 + {?} // => "1[object Object]": 객체를 문자열로 바꾼 후 이어붙이기
true + true // => 2: 불리언 값을 숫자로 바꾼 후 더하기
2 + null // => 2: null 값을 0으로 바꾼 후 더하기
2 + undefined // => NaN: undefined를 NaN으로 바꾼 후 더하기

4.8.2 단항 산술 연산자

증가(++)

표현식 ++xx=x+1과 항상 같지 않다. ++ 연산자는 절대 문자열 결합을 하지 않고, 항상 피연산자를 숫자로 바꾼 후에 값을 하나 증가시킨다. 예를 들어, x가 문자열 “1”이면 ++x는 숫자 2가 되지만 x+1은 문자열 “11”이 된다.


4.9 관계형 표현식

4.9.1 동치와 부등치 연산자

==와 === 연산자 모두 주어진 두 값이 같은지를 확인하는 데 쓰이지만 같음을 정의하는 기준이 서로 다르다. 두 연산자 모두 피연산자 타입을 가리지 않고, 주어진 피연산자들이 같으면 true, 다르면 false를 반환한다. === 연산자는 일치(엄격한 동치) 연산자로 알려져 있는데, 같음을 정의하는 기준을 매우 엄격하게 정의하여, 두 피연산자가 ‘일치’하는지 확인한다.

자바스크립트는 =(할당), ==(동치), ===(일치) 연산자를 지원하고 있다.

4.9.2 비교 연산자

비교 연산자는 피연산자 타입에 제한이 없다. 하지만 오직 숫자와 문자열만 비교할 수 있기 때문에, 숫자나 문자열이 아닌 피연산자는 먼저 변환된다.

문자열 비교는 대소문자를 구분한다. 모든 ASCII 대문자는 모든 ASCII 소문자보다 작다. 대소문자를 구분하지 않고 문자열을 비교하려면, 우선 String.toLowerCase()String.toUpperCase() 메서드를 사용해야 한다.

4.9.3 in 연산자

in 연산자는 좌변의 피연산자로 문자열(또는 문자열로 변환될 수 있는 것)을 받고, 우변의 피연산자로는 객체나 배열을 받는다. 좌변 값이 우변 객체의 프로퍼티 이름에 해당할 경우 연산 결과는 true이다.

1
2
3
4
5
6
7
8
var point = { x:1, y:1 };          // 객체 정의
"x" in point // => true: 프로퍼티 x가 있다.
"z" in point // => false: 프로퍼티 z가 없다..
"toString" in point // => true: 상속된 프로퍼티
var data = [7,8,9]; // 원소가 0, 1, 2 위치에 차례로 7, 8, 9
"0" in data // => true: 배열에 0번째 원소가 있기 때문
1 in data // => true: 배열에 1번째 원소가 있기 때문
3 in data // => false: 배열에 4번째 원소가 없기 때문

4.9.4 instanceof 연산자

instanceof 연산자는 좌변의 피연산자로 객체를, 우변의 피연산자로 객체 클래스의 이름을 받는다. 자바스크립트에서 객체의 클래스는 객체를 초기화하는 생성자 함수로부터 정의된다. 그러므로 instanceof의 우변 피연산자는 함수가 되어야 한다.

1
2
3
4
5
6
7
8
var d = new Date();          // Date() 생성자로 새로운 객체를 생성한다.
d instanceof Date; // => true: d는 Date()에 의해 생성되었다.
d instanceof Object; // => true: 모든 객체는 Object의 인스턴스.
d instanceof Number; // => false: d는 Number의 객체가 아니다.
var a = [1, 2, 3]; // 배열 리터럴 문법으로 새로운 배열을 생성한다.
a instanceof Array; // => true: a는 배열이다.
a instanceof Object; // => true: 모든 배열은 객체다.
a instanceof RegExp; // => false: 배열은 정규 표현식이 아니다.


4.10 논리 표현식

4.10.1 논리 AND (&&)

&& 연산자의 피연산자로 반드시 불리언 값이 올 필요는 없다. 모든 자바스크립트 값은 true 또는 false로 평가될 수 있기 때문이다. 피연산자 모두 true로 평가되는 값이면, && 연산자는 true로 평가되는 값을 반환한다. 하지만 적어도 하나의 피연산자가 false로 평가될 경우에는 false로 평가되는 값을 반환한다.

&& 연산자의 특성을 ‘단축 평가’라고도 부르고 다음과 같이도 사용 가능하다.

1
2
if (a == b) stop();
(a == b) && stop();

&& 연산자는 우변 표현식을 평가할 수도, 하지 않을 수도 있기 때문에 && 우변에 부수 효과가 일어나는 표현식(하당, 증가, 감소, 함수 호출)을 사용할 때는 각별히 주의해야 한다. 이러한 부수 효과가 일어나는 표현식은 && 좌변 값에 따라 실행 여부가 결정되기 때문이다.

4.10.2 논리 OR (||)

|| 연산자는 일반적으로, 다음 코드와 같이 여러 값중에 최초로 true로 평가되는 값을 선택하는 경우에 사용된다.

1
2
3
4
// max_width가 정의되어 있으면 이것을 사용한다.
// 이 외의 경우 preference 객체에 속한 값을 찾아본다.
// 그것조차 정의되어 있지 않을 경우 하드 코딩된 상수를 사용한다.
var max = max_width || preferences.max_width || 500;


4.13 기타 연산자들

4.13.2 typeof 연산자

typeof의 피연산자 값이 null일 때 연산자는 “object”를 반환한다. 만약 다른 Object들과 null을 구분하고 싶다면, typeof를 사용하기 보다는 명시적으로 null인지를 테스트해야한다.

typeof 연산자는 함수를 제외한 모든 객체와 배열을 “object”로 평가하기 때문에, 객체를 다른 원시 타입과 구분하는 용도로만 사용할 수 있다. 객체의 클래스를 구분하기 위해서는 instanceof 연산자나 class 속성 또는 constructor 프로퍼티와 같은 다른 수단을 사용해야 한다.

자바스크립트에서 함수는 객체의 일종이지만, typeof 연산자는 함수들이 자신의 반환 값을 가지고 있다는 점 때문에 일반 객체와는 충분히 다르다고 본다. 자바스크립트에서는 함수와 ‘호출 가능한 객체’ 사이에 미묘한 차이점이 있다. 모든 함수는 호출 가능하다. 하지만 실제로는 함수가 아닌데도 함수처럼 호출이 가능한 객체도 있을 수 있다.

ECMAScript 5 표준은 typeof 연산자가 모든 호출 가능한 객체에 대해 일반 개체든 호스트 객체든 관계없이 ‘function’을 반환하도록 명세를 확장했다.

4.13.3 delete 연산자

delete는 단항 연산자이며, 피연산자로 지정된 객체 프로퍼티, 배열 원소 또는 변수의 삭제를 시도한다. delete 연산자는 보통 연산자가 가진 부수 효과(프로퍼티 삭제) 때문에 사용하는 것이며, 연산자가 반환하는 값 때문에 사용하는 것이 아니다. (단, 배열의 원소를 delete 연산자를 사용하여 삭제해도 배열의 길이는 변하지 않는다.)

삭제된 프로퍼티나 배열의 원소는 단순히 undefined 값으로 설정된 것이 아니라는 점을 유의해야한다. 어떤 프로퍼티가 삭제되면 그 프로퍼티는 더 이상 존재하지 않는다. 그런데 존재하지 않는 프로퍼티에 접근하려고 해도 undefined가 반환되므로, 프로퍼티가 객체에 존재하는지 여부를 검사하려면 in 연산자를 쓰면 된다.

그러나 모든 변수나 프로퍼티를 삭제할 수는 없다. var 문으로 선언한 사용자 정의 변수나 내장 코어 프로퍼티, 클라이언트 측 프로퍼티는 삭제할 수 없다. function 문으로 정의한 함수와 함수 매개변수도 삭제할 수 없다.



출처 : “JavaScript: The Definitive Guide, by David Flanagan (O’Reilly). Copyright 2011 David Flanagan, 978-0-596-80552-4”

댓글

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×