티스토리 뷰

책이름: You don't know JS : 타입과 문법, 스코프와 클로저
주관적으로 머리에 남기고 싶은 부분들만 정리하였습니다. 자세한 내용은 책을 참고하시는게 좋습니다. 

배열(Array)

자바스크립트 배열은 타입이 엄격한 다른 언어와 달리 문자열, 숫자, 객체 심지어 다른 배열(다차원 배열)이나 어떤 타입의 값이라도 담을 수 있다. 

  • 배열 크기는 미리 정하지 않고 선언가능, 원하는 값을 추가할 수 있다. 
  • (주의)배열 값에 delete 연산자를 적용하면 slot(슬롯)을 제거할 수 있찌만 마지막 원소까지 제거해도 length프로퍼티 값은 바뀌지 않는다 *빈/빠진 슬롯이 있는 구멍난 배열 예시는 아래에 있다.
  • 배열 인덱스는 숫자이지만 배열 자체도 하나의 객체이다. 그렇기 때문에 키/프로퍼티 문자열을 추가할 수 있다(but, 배열 length는 증가하지 않는다. 왜저래)
  • 키로 넣은 문자열 값이 표준 10진수 숫자로 타입이 바뀌면, 마치 문자열 키가 아닌 숫자 키를 사용한 것 같은 결과가 초개되기 때문에 주의해야 한다. 그렇기 때문에 일반적으로 배열에 문자열 타입의 키/프로퍼티를 두는 것은 지양해야 한다. 만약 꼭 필요하다면 객체를 대응하고 배열 원소의 인덱스는 확실히 숫자만 쓰자 * 이 부분도 아래 예시 참고
const a = [ 1, "2", [3]];
a.length; //3
a[2][0] === 3 // true

//* 빈/빠진 슬롯이 있는 구멍난 배열 예시
const a = [];
a[0] = 1;
// a[1] 슬롯 건너뜀
a[2] = 3;

a[1]; //undefined 
a.length; // 3

//*키로 10진수 숫자 문자열 값을 넣었을 경우, 주의 
const a =[];
a["13"] = 42;
a.length //14

유사 배열 

유사 배열 값(숫자 인덱스가 가리키는 값들의 집합)을 진짜 배열로 바꾸고 싶을 때는 기존 indexOf() concat() forEach() 등의 배열 유틸리티 함수를 사용했지만 ES6 부터는 기본 내장 함수 Array.from()을 사용하면 된다. 


문자열(String)

문자열 문자의 배열, 자바스크립트 문자열은 실제로 생김새만 비슷할 뿐 배열과 같지는 않다.

문자열은 유사 배열로 생각하면 된다. 둘 다 length프로퍼티, indexOf() 메서드(ES5 배열에만 있음), concat() 메서드를 가진다. 문자열은 불변 값이지만 배열은 가변 값이다. 문자열은 a[1]로 접근하는 것보다 a.charAt(1)으로 접근하는 것이 맞다. 

  • 문자열은 불변 값이므로 문자열 메서드는 그 내용을 바로 변경하지 않고 항상 새로운 문자열을 생성한 후 반환한다. 반면 대부분의 배열 메서드는 그 자리에서 곧바로 원소를 수정한다. 
  • 문자열은 불변 값이라 바로 변경되지 않으므로 배열의 가변 메서드는 통하지 않고, 그래서 빌려 쓰는 것 또한 안된다. 
  • 그래서 우선 문자열을 배열로 바꾸고 원하는 작업을 수행 후 다시 문자열로 되돌리는 것이 또 다른 꼼수이다. (예시 참고)
  • 문자열 자체에 어떤 작업을 빈번하게 수행하는 경우라면 문자열을 문자 단위로 저장하는 배열로 취급하는 것이 더 나을 수 있다. 

문자열을 역순서로 만드는 꼼수 방법

//a 라는 문자열을 배열로 분할(split) 그 다음 역순으로 원소들을 바꿔준다(reverse) 다시 문자열로 합친다(join)
const c = a.split("").reverse().join("");
주의: 복잡한 유니코드 문자가 섞여있는 경우(특수 문자, 멀티바이트 문자 등) 이 방법은 통하지 않음 제대로 처리하려면 유니코드를 인식하는 정교한 라이브러리 유틸리티가 필요하다. 

NaN

"숫자 아님" 보다는 유효하지 않은 숫자, 실패한 숫자 또는 몹쓸 숫자 정도로 해석하는 것이 좋다.

  • NaN은 다른 어떤 NaN과도 같지가 않다.(자기랑 비교해도 false로 뜸) 사실상 반사성이 없는(식별되지 않는)유일한 값이다. 따라서 NaN !== NaN 이다. 
  • 그렇다면 NaN의 여부는 어떻게 판가름하는가 window.isNaN()라는 내장 전역 유틸리티 함수(window 생략가능)를 쓰면 된다. -> 하지만 말 그대로 숫자인지 아닌지만 평가하기 때문에 결과가 정확할 수 없다. (ES6 Number.isNaN()과는 다른 애다)
  • ES6부터는 Number.isNaN()이 등장하여 ES6 이전 브라우저에서는 폴리필을 쓰면 안전하게 NaN여부를 체크할 수 있다. 

ES6 Number.isNaN() 폴리필 예시 

// ES6 Number.isNaN 폴리필
{
  if (!Number.isNaN) {
    Number.isNaN = function (n) {
      return typeof n === 'number' && window.isNaN(n);
    };
  }

  const a = 2 / 'foo';
  const b = 'foo';

  console.log(Number.isNaN(a)); //true
  console.log(Number.isNaN(b)); //false
}

값 vs 레퍼런스

다른 언어에서 값은 사용하는 구문에 따라 값-복사 또는 레퍼런스 복사의 형태로 할당/전달한다. 

레퍼런스는 포인터의 특수한 형태로 다른 변수의 포인터를 ( 꼭 Alias 처럼) 가진다.

레퍼런스 인자를 선언하지 않으면 전달한 값은 아무리 복잡한 객체일지라도 언제나 복사된다. 

 

자바스크립트는 포인터라는 개념 자체가 없고 참조하는 방법도 다르다. 우선 어떤 변수가 다른 변수를 참조할 수 없다. 

자바스크립트에서 레퍼런스는 공유된 값을 가리키므로 서로 다른 10개의 레퍼런스가 있다면 이들은 저마다 항상 공유된 단일 값을 개별적으로 참조한다. 값의 타입으로만 값-복사, 레퍼런스-복사 둘 중 한쪽이 결정된다. 


Chapter3 네이티브 

p. 79

Symbol()

심볼은 ES6에서 선보인, 새로운 원시 값 타입이다. 심볼은 충돌 염려없이 객체 프로퍼티로 사용 가능한, 특별한 '유일 값'이다(절대적으로 유일함이 보장되지는 않음). 주로 ES6의 특수한 내장 로직에 쓰기 위해 고안되었지만 얼마든지 심볼을 정의할 수 있다. 

  • 심볼을 정의하려면 Symbol() 네이티브를 사용해야 한다. Symbol()은 앞에 new를 붙이면 에러가 나는 유일한 네이티브 '생성자'이다. 
  • 사용목적은 대부분 전용 혹은 특별한 프로퍼티로 사용한다.

심볼은 프로퍼티명으로 사용할 수 있으나, 프로그램 코드나 개발자 콘솔 창에서 심볼의 실제 값을 보거나 접근하는 것은 불가능하다.  심볼 값을 콘솔 창에 출력해보면 Symbol( Symbol.create)로 나온다. 

//ES6에 추가된 새로운 원시값
{
  const mysym = Symbol('내꺼임');
  console.log(mysym); //Symbol(내꺼임)
  mysym.toString(); //'Symbol(내꺼임)'
  typeof mysym; //'symbol'
  const a = {};
  a[mysym] = 'hello';
  Object.getOwnPropertySymbols(a); //[Symbol(내꺼임)]
}
_가 붙은 프로퍼티 명 의미: "이건 전용/특수/내부 프로퍼티입니다. 건드리지 마세요!"  이 프로퍼티 명도 심볼에 의해서 완전히 대체될 가능성이 높다고 한다. 

chater3 요약 정리:

자바스크립트는 원시 값을 감싸는 객체 래퍼, 즉 네이티브(String, Number, Boolean 등)를 제공한다. 객체 레퍼에는 타입별로 쓸 만한 기능이 구현되어 있어 편리하게 사용할 수 있다.

"abs"같은 단순 스칼라 원시 값이 있을 때, 이 값의 length 프로퍼티나 String.prototype에 정의된 메서드를 호출하면 자바스크립트는 자동으로 원시 값을 '박싱(해당되는 객체 래퍼로 감싼다)'하여 필요한 프로퍼티와 메서드를 쓸 수 있게 도와준다. 

chapter 4(강제변환)까지 읽음

챕터4의 경우는, 유용하지만 필요할 때 보고 적용하는 것이 좋을 거 같아 따로 적지는 않았음 명시적, 암시적 변환, falsy 값 truthy값 && || 등 비교 연산자에 대한 내용이 나온다.

chapter5(문법)까지는 쭉 훑는 식으로 읽고 내가 알고싶은 뒷챕터인 "스코프와 클로저" 관련해서 한 번 정독한 다음 정리해야 겠다.

댓글