[javascript] 문자열과 문자열 객체의 차이

자바스크립트에는 문자열을 저장하는 2가지 데이터 타입이 있습니다.

자바스크립트에 원래 있던 문자열 타입(원형 문자열), 그리고 문자열 객체가 있습니다.

둘은 문자열 데이터를 담는 면에서는 같지만 그 사용 방법은 여러가지로 다른 데이터 타입입니다.

let str1 = '문자열';let str2 = new String('문자열');

str1은 문자열 타입입니다. 문자열 리터럴(작은 따옴표, 또는 큰 따옴표로 값을 직접 지정)로 생성합니다. 자바스크립트 초기부터 있던 원시 데이터 타입으로 문자형 변수로 표현이 됩니다. 별도의 생성자가 없습니다.

str2는 문자열을 담고 있는 String 표준 전역 객체입니다. 별도의 데이터 타입이 아닌 자바스크립트의 기본 객체입니다. new 는 다른 언어와 동일하게 새 객체를 생성하는 생성자입니다.

str1 과 str2의 데이터 타입을 콘솔에 출력해보면 

str1은 "string"(문자열), str2는 "object"(객체) 로 출력됩니다.

하지만 str1 과 str2를 서로 비교하면 조금 다른 결과가 됩니다.

값을 비교하는 비교 연산자로 비교하면 str1 == str2 는 true가 됩니다. str1의 문자열 값과 str2 객체의 값을 비교하기 때문에 true가 됩니다. 값을 비교하는 연산자이므로 데이터 타입이 다르기 때문에 문자열 객체를 문자열로 캐스팅하게 되고, 참조 객체에서 값을 가져와(str2.valueOf()) 비교하게 됩니다.

타입까지 엄격하게 비교하는 삼등호 연산자로 비교하면 str1 === str2 는 false가 됩니다. 문자열과 객체 타입으로 데이터 타입이 서로 다릅니다.

조금 다르게 비교를 하면 

'문자열' == str1, '문자열' === str1 은 모두 true 를 반환합니다. 

왼쪽 항의 '문자열' 은 비교전에 문자열 타입이 되기 때문에 타입도 같고, 값도 같습니다.

반면, new String('문자열') == str2, new String('문자열') === str2 는 모두 false를 반환합니다.

여기서 중요한 차이가 발생합니다.

문자열 객체를 생성하는 new String('문자열') 은 문자열 객체를 반환하는게 아니라 문자열 객체의 참조 주소(메모리 주소)를 반환합니다.

즉, 왼쪽 항의 새로운 문자열 객체의 참조 주소와 str2 문자열 객체의 참조 주소를 비교하기 때문에 false가 됩니다.

타입이 같기 때문에 앞에서와 같은 값을 가져오는 캐스팅이 발생하지 않고, 참조 주소값을 그대로 비교하게 됩니다.

당연히 '문자열' == str2,  '문자열' == new String('문자열')은 타입 캐스잉이 되기 때문에 모두 true를 반환합니다.

변수에 대입하지 않은 new String('문자열') 을 콘솔에 출력해보면 '문자열' 값이 출력됩니다.

console.log 출력시 반환된 문자열 객체 참조 주소의 문자열 값을 가져와 출력한 것입니다.

예를 들어

new String('문자열') == new String('문자열'), new String('문자열') === new String('문자열') 은 모두 false를 반환합니다. 각각 새로 생성된 객체의 반환된 메모리 참조 주소를 비교하기 때문에 같을 수가 없습니다.

문자열 객체를 생성해 사용할 경우 생성자 자체를 비교하면 안되며, 반드시 변수에 대입한 후 사용해야 합니다.

또 하나 eval() 은 문자열을 자바스크립트 소스 코드로 변환해 실행 코드로 만들어주는 전역 함수입니다.

예를 들어

const calc1 = '1 + 2 * 3';const calc2 = new String('1 + 2 * 3');

이런 문자열과 문자열 객체 2가지를 eval() 을 하면

eval(calc1); // Number 타입 7 반환eval(calc2); // '1 + 2 * 3' 문자열을 가진 문자열 객체 그대로 반환

eval() 은 그 정의가 문자열을 입력 받아 소스 코드로 전환을 해주는 함수입니다.

문자열이 아닌 객체를 파라메터로 받을 경우 객체를 그대로 반환합니다.

문자열 객체는 메서드 valueOf() 를 이용해 문자열 원형으로 변환할 수 있습니다.

앞의 calc2 는 eval(calc2.valueOf()) 로 eval(calc1) 과 동일한 결과를 얻을 수 있습니다.

var str1 = '문자열데이터';var str2 = new String('문자열데이터');
var str3 = new String('문자열데이터');
var str4 = str3.valueOf();
var calc1 = '1+2*3';
var calc2 = new String('1+2*3');

console.log(typeof(str1));
console.log(typeof(str2));
console.log(typeof(str3));
console.log(typeof(str4));
console.log(str1==str2);
console.log(str1===str2);
console.log(str2==str3);
console.log(str2==str3.valueOf());
console.log(new String('문자열') == str2);
console.log(new String('문자열') === str1);
console.log(new String('문자열') == '문자열'); //trueconsole.log(new String('문자열') == str1); //true
console.log(new String('문자열') == new String('문자열'));
console.log(new String('문자열') === new String('문자열'));
console.log(str2 == str3);console.log(str2 === str3);
console.log('문자열' == new String('문자열'));
console.log('문자열' === new String('문자열'));
console.log(typeof(eval(calc1)));
console.log(typeof(eval(calc2)));

var calc3= eval(calc2);
console.log(typeof(calc3));