일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- nodeJS
- 자바스크립트
- CAS
- Effective Java
- javascript 값
- spring security
- java.util.LinkedHashMap cannot be cast
- 자바
- Redis
- 이펙티브자바
- java
- javascript
- javascript value
- javascript 기초
- webpack
- Spring Session
- spring batch #스프링 배치 #스프링 배치 중복 실행
- javascript type
- Spring
- you don't know js
- requestbody
- 이펙티브 자바
- effectivejava
- JetBrains
- webstorm
- ES6
- ECMA2015
- Babel
- javascript native
- Intellij
- Today
- Total
귀찮지만 만들어보자
you don't know javascript 리뷰 - 2장 값 본문
2. 값
2-1. 배열
: js의 배열은 다른 언어와는 다르게 어떤 값도 담을수 있고, 크기를 정하지 않고도 선언이 가능하다
java의 배열과는 여러모로 다르다. python의 list와 비슷하면서 살짝 또 다름
* 배열 값에 delete 연산자를 적용하면 값을 제거할 수 있지만 length가 줄어들지는 않는다. splice를 사용하자
* 배열 자체도 하나의 객체(typeof 배열 -> "object")여서 키 / 프로퍼티 문자열을 추가할 수 있다
-> 그러나 length는 증가하지 않는다. 또 여기서 한가지 더 주의해야할 점은
var a = [];
a["13"] = 42;
a.length; // 14
이런 식으로 키로 넣은 문자열 값이 표준 10진수 숫자로 타입이 바뀌게 되면 숫자키를 입력한것처럼 length가 증가한다이런 거지같은 경우가...
2-1-1. 유사 배열
: 유사 배열(숫자 인덱스가 가리키는 값들의 집합)을 진짜 배열로 바꾸고 싶을때, 보통은 배열 유틸리티 함수
(indexOf, concat, forEach) 등을 사용한다
: 함수에서 arguments 객체를 사용해서 인자를 배열로 치환할때는 slice를 많이 사용한다
ES6부터는 내장함수 Array.from(arguments); 가 이 일을 대신하기 때문에 ES6부터는 비권장
2-2. 문자열
: 생김새는 배열과 비슷하지만 엄연히 다르다. 가장 큰 차이점은 문자열은 불변 / 배열은 가변 이라는 점.
var a = “foo”;
var b = [“f”, “o”, “o”];
이런 두 값에서 a[1] 처럼 문자열의 특정 문자에 접근하는 형태가 ie 구버전에서는 에러로 인식한다. 문자열이니까 -_-;
a.charAt(1) 이런식으로 접근
: 또 다른 특징은 문자열은 내부의 값을 변경할때 불변값이므로 새로운 객체를 생성해서 반환한다.
반면 배열은 즉시 값을 교체한다.
* 문자열을 다룰 때 유용한 대부분의 배열 메서드는 사실상 문자열에는 쓸 수 없다.
ex) 문자열을 뒤집으시오
var a = “foo”;
var c = a.split(“”).reverse();
* 여기서 reverse() 함수는 배열에서밖에 사용할 수 없다
#유의사항 - 복잡한 문자(멀티바이트 문자, 특수 문자)가 섞여있는 경우에는 이 방법이 통하지 않으므로 유니코드 인식 라이브러리를 사용하자
2-3. 정수
: js의 숫자 타입은 number가 유일하며 정수와 부동소수점 숫자 모두를 아우른다.
* 정수와 부동소수점의 차이를 두지 않아 여태 욕을 많이 먹었다고함
* 그래서 42.0 과 42는 같은 값이다
2-3-1. 숫자 구문
: 부동소수점 숫자와 정수를 구분하지 않기 때문에 소수점 이하의 자리를 나타내고 싶을때는 toFixed() 함수를 사용해서 문자열로 반환하게 된다
: 큰 숫자는 지수형으로 표시한다 ex) var a = 5E3; -> 5 * 10^3
2-3-2. 아주 작은 소수 값
: 0.1 + 0.2 === 0.3 // false 라고 한다 -_-;; (이진 부동소수점 연산)
* 이진 부동소수점으로 나타낸 0.1과 0.2가 원래의 값과 미세하게 차이가 나서 저런 결과가 나온다고한다
* 다음과 같은 폴리필을 사용하면 해결 가능하다고함
if (!Number.EPSILON) {
Number.EPSILON = Math.pow(2,-52);
}
* 여기서 EPSILON은 숫자의 미세한 오차값을 뜻하는데 해당 폴리필을 적용하면 오차를 해결할 수 있다
2-3-3. 안전한 정수 범위
: 정수 범위는 대략 -9000조에서 +9000조이다. 해당 범위 내에서의 연산은 안전을 보장받지만 더 큰 수를 다뤄야할 경우에는 BigNumber Utility의 사용을 권장함
2-3-4. 정수인지 확인
: ES6 이후에는 isInteger() 함수를 사용해서 부동소수점 숫자와 정수를 구분 가능하다.
: 그 이전 버전에서는 정수 확인 폴리필을 적용해야 한다
: ES6 이후에는 안전한 정수인지도 지원한다. 역시 하위버전에서는 폴리필을 사용해서 적용해야한다
2-3-5. 32비트 (부호 있는) 정수
: 실제로 정수의 안전 범위는 9000조(53비트)에 이르지만 32비트에서만 가능한 연산이 있으므로 실제 범위는 훨씬 줄어든다
* 비트연산이 그러하다
2-4. 특수값 개인적으로는 js를 별로 좋아하지 않는 이유이다
2-4-1. 값 아닌 값
: undefined 타잆의 값은 undefined, null 타입의 값도 역시 null 뿐이다.
그래서 이 두 가지는 빈 값이나(~원빈아님ㅎ~) 값이 아닌 값을 나타낸다.
* 다른의미로 사용될 경우
1) null은 빈 값 / undefined는 실종된 값
2) null은 값이 있다가 없어진 상태 / undefined는 값을 아직 가지지 않은 것
2-4-2. Undefined
: “use strict” 모드가 아닐때 전역스코프에서 undefined 식별자에 값을 할당할 수 있다 세상에..
트롤링 할게 아니라면 쓰지 말자..
* void 연산자
- 값이 존재하는 곳에서 그 값이 undefined가 되어야 좋을 경우에만 사용해야함.
- 어떤 연산 이후 리턴 값이 undefined가 되어야 하는 경우에 사용한다
2-4-3. 특수 숫자
- NaN 이것도 싫다..
var a = 2 / “foo” ; // NaN
typeof a === “number”; // true
: NaN은 숫자가 아니라는 뜻인데 typeof 연산자를 먹였을때 true가 나오는 황당한 경우가…
: 게다가 NaN은 동등연산자가 먹히질 않는다. 같은 NaN이라도 다른 취급..;
var a = 2 / “foo”;
var b = “foo”;
: a 는 NaN 이 명백하고 , b 는 “foo”라는 문자열이다.
그런데 이 두가지 변수에 isNaN() 함수를 적용하면 둘 다 똑같이 true가 떨어진다.
그러니까 isNaN의 기능은 숫자인지 아닌지밖에 구분을 못하는 반쪽짜리인 셈인데.. ES6에서는 Number.isNaN()이 제대로 구현이 되어있다.
하위버전에서는 또 폴리필을 적용해야 온전히 사용이 가능하다
* 유감스럽게도 ES6 하위버전에서 isNaN()을 사용해서 코딩중이라면 폭탄을 심어둔 셈이라고 한다내가 묻어둔 폭탄이 몇개 생각난다…
- 무한대
var a = 1 / 0;
이 부분은 의외로 잘 정의되어 있어서 Infinity라는 결과값이 나온다.
- 0
: js에서는 -0과 +0이 존재한다
var a = 0 / -3; // -0
* IE는 또 -0 +0 구분이 없다고 한다 얘네는 왜 지네만 다른게 이렇게 많은지 모르겠다
* 정말 어처구니 없게도 JSON.parse(-0) 은 결과값이 -0인데 JSON.stringify(-0)은 결과값이 0이다
2-5 값 vs 레퍼런스
var a = 2;
var b = a; // ‘b’는 언제나 ‘a’에서 값을 복사한다
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // ‘d’는 공유된 ‘[1,2,3]’ 값의 레퍼런스다
d.push(4);
c; // [1,2,3,4]
d; // [1,2,3,4]
: js에서 단순 값(primitive value)는 항상 값을 복사하는 방식으로 할당/전달된다
: 객체나 함수등 합성 값들은 레퍼런스를 복사해서 할당/전달 한다
: 값을 공유한다고 생각하면 편하지 않을까?
var a = [1,2,3];
var b = a;
b = [4,5,6];
: b에 새로운 값을 할당하는 것. 때문에 a에 영향을 끼치지 않는다
function foo(x) {
x.push(4);
x; // [1,2,3,4]
x = [4,5,6];
x.push(7);
x; // [4,5,6,7]
}
var a = [1,2,3];
foo(a);
a // [1,2,3,4]
: 이전 예제의 연장선상에 있는 내용이다. 혼동될 수 있지만 전술한 내용을 확실하게 이해한다면 어렵지 않다