자바스크립트 재공부 이유와 목적

나는 자바스크립트를 에러없이 코딩할 수 있다. 방학 프로젝트 때 처음으로 자바스크립트를 처음 접하고 쓰면서도 문법적인 오류가 없이 코드가 돌아가는데 초점을 뒀었고 뭐가 잘못됐고 부족했고를 느끼지 못했다.

이런 내가 자바스크립트를 다시 공부하게 된 계기는 크게 3가지가 있다.

  1. 네이버 핵데이에서 멘토님의 내 코드 리뷰: “자바스크립트를 처음 쓰시는게 느껴졌어요.”
  2. 하조은 선배님의 특강: “자바스크립트에 대한 이해 없이 프레임워크를 바로 공부하면 안되요.”
  3. 마지막으로 갑자기 시작된 스타트업 프론트엔드 개발 인턴

원래 다시 공부하려고 마음 먹은 찰나에 좋은 인턴 기회가 생겨서 프론트엔드 개발인턴 일을 시작하게 되었고 다음주 본격 출근 전에 공부를 다시 해보려고 한다.

이 공부의 목적은 자바스크립트를 사용해본 경험을 넘어선 자바스크립트의 특성과 원리를 이해하는 것이다. Inside Javascript라는 책을 읽으며 배운 내용을 정리해보자.


객체 == 참조 타입

자바스크립트에서는 기본 타입인 숫자, 문자열, 불린값, null, undefined를 제외한 모든 값은 객체로 취급된다. 이러한 객체는 자바스크립트에서는 참조 타입으로 불려진다. 그 이유는 객체의 모든 연산이 실제 값이 아닌 참조값으로 처리되기 때문이다.

var objA = {
    val : 40
};
var objB = objA;
objB.val = 50;

객체 비교

이 때 objA.val의 값은 얼마일까? 40이라고 생각할 수 있지만 objA와 objB는 같은 객체를 참조하고 있기 때문에 50이 된다.

두개의 객체의 비교 연산을 진행할 때는 객체의 실제 값이 얼마인지를 비교하는 것이 아닌 객체의 참조값이 같은지 비교한다.(기본 타입 비교 시는 실제값을 비교한다.)

var objA = { val: 100}
var objB = { val: 100}
var objC = objB;

console.log(objA == objB); //false
console.log(objB == objC); //true

참조에 의한 함수 호출 방식

기본 타입은 함수를 호출할 때 실제 값을 복사해서 넘겨주는 Call by value 방식으로 진행된다. 하지만 참조 타입은 값을 복사하지 않고 참조값이 전달된다. 다음 코드를 보면 이해가 빠를 것이다.

var a = 100;
var objA = { value: 100};

function changeArg(num, obj){
    num = 200;
    obj.value = 200;
}

changeArg(a, objA);

console.log(a); //100
console.log(objA); //{ value: 200 }

함수 내에서 num과 obj의 value를 변경해줬지만 num은 a의 복사값을 바꿨으므로 a의 값은 변경되지 않고 objA는 참조값을 전달했으므로 값이 바뀌게 된다.


프로토타입

모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다. 이러한 부모 객체를 프로토타입이라고 한다. 다음 예제에서 보듯이 우리는 toString()이라는 함수를 정의하지 않았음에도 toString()이라는 함수를 사용할 수 있다.

var objA = { name : 'foo', age : 30};
objA.toString();

이러한 함수는 Object.prototype에 있는 함수 중 하나로 object 생성시 자연스럽게 상속받게 된다. 모든 객체는 자신의 프로토타입을 가지는 [[Prototype]]라는 내부 프로퍼티를 가진다(크롬에서는 이를 __proto__로 표기하고 있다.)


배열

배열은 배열 리터럴을 통해 생성될 수도 있고, 객체가 동적으로 프로퍼티를 추가할 수 있듯이, 요소를 추가할 수도 있다. 이때 값을 순차적으로 넣을 필요 없이 아무 인덱스에나 동적으로 추가도 가능하다.

값이 없는 위치에는 undefined가 출력된다.

var arr = [];
arr[0] = 100;
arr[3] = 'Yes';
arr[7] = true;
console.log(arr); // [100, undefined * 2, 'Yes', undefined * 3, true]

배열의 length

이것은 배열의 원소의 개수가 아닌 배열의 가장 큰 인덱스에 1을 더한 값이다.

배열 표준 메서드와 length

push를 할 시에는 arr.length가 가르키는 인덱스에 해당하는 위치에 원소를 추가한다.

배열과 객체의 프로토타입 차이

객체의 프로토타입은 Object.prototype이라고 앞서 말했다.

배열의 프로토타입은 Array.prototype인데 Array.prototype의 프로토타입이 Object.prototype이다. 때문에 배열은 Array와 Object의 표준 함수를 모두 사용할 수 있다.

배열도 객체이기 때문에 다음과 같이 객체의 프로퍼티를 추가할 수 있다. 이 경우 length는 변하지 않는다.

var arr = [1, 2, 3];
arr.name = 'number_array';

배열의 요소 삭제

배열의 요소를 삭제할 수 있다.
delete를 사용한다면 해당 위치의 값을 undefined로 바꾸게 된다. splice() 함수를 사용하면 아예 원소 자체를 삭제 할 수 있다.

기본 타입과 표준 메서드

기본 타입 같은 경우에는 object가 아닌데 표준 메서드를 어떻게 이용할까?
기본 타입에서 표준 메서드 호출 시 해당 값이 객체로 변환된 다음에 메서드를 호출하고 다시 기본값으로 복귀한다.


연산자

덧셈의 경우 숫자와 숫자 연산인 경우만 결과가 숫자로 남고 나머지 경우는 모두 문자열 연결 연산이 이주어 진다.

null, 배열, 객체의 typeof 연산자 결과는 ‘object’이다.

==와 === 연산자

==는 타입이 다른 경우에 타입 변환 과정을 거친 다음에 비교를 진행한다.

===는 타입이 다른 경우에는 타입을 변경하지 않고 비교한다.

console.log(1 == '1'); //true
console.log(1 === '1'); //false

타입 변환에 따른 잘못된 결과를 얻을 수 있으므로 자바스크립트 코딩 가이드에서는 == 연산자로 비교하는 것을 추천하지 않는다.

!! 연산자

!!는 값을 boolean 값으로 변환시켜준다.

숫자인 경우, !!0만 false
문자인 경우, !!’‘만 false
null, undefined는 무조건 false
object는 무조건 true

이상으로 3장 데이터 타입과 연산자 정리를 마치겠다.

참고서적 : 인사이드 자바스크립트 by 송형주, 고현준