2. 값_1

악음·2021년 7월 9일
2

i will know javascript

목록 보기
4/12
post-thumbnail

배열, 문자열, 숫자는 모든 프로그램의 가장 기본적인 구성 요소이지만 자바스크립트에서는 독특한 특성을 갖고 있어 개발자들을 웃게도, 울게도 만든다 자바스크립트에 내장된 값 타입과 작동 방식을 살펴보고 "정확하게" 사용할 수 있도록 하자

2.1 배열

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

var a =[1,"2",[3]];
a.length // 3
a[0]===1 //true
a[2][0]===3 //true

배열의 크기는 미리 정하지 않고도 선언할 수 있으며 원하는 값을 추가하면 된다.


// 배열값에 delete a[0] 을 할경우 슬롯을 제거 할 순 있지만 총 length을 재거 할 순없다
let a =[1,2,3,4,5,]
delete a[0]
a // [empty, 2, 3, 4, 5]

let a = []
a[0]=1
a[2]=3
a[1] //undefined
a // [1,empty,3]

이런 코드의 빈슬룻은 undefined를 토해내기 때문에 혼란을 부추길 수 있다.
물론 a[1]을 보면 undefined가 나오지만 명시적으로 a[1]=undefined라고 셋팅한 것과는 똑같지 않다.

배열도 객체이므로 키/프로퍼티 물자열을 추가할 수 있다. 하지만 배열의 length가 증가하지 않는다 즉 배열은 그냥 순수히 index를 활용하여 관리하는게 좋겠다.
(아마도 string타입의 키값(인덱스)는 length 카운트 할때 포함되지 않는 것같다 마치 오브젝트의 length를알 수 없는 것처럼

let a ={a:1,b:2}
typeof a // "object"
a.length // undefined

아래는 키/프로퍼티를 배열에 추가하는 모습이다.

let a = []
a[0]=1
a["footbar"] =2
a.length // 1
a["foobar"] 

여기서 주의해야할 점은
키값을 10진수를 표현한 string이면 마지 문자열 키가 아닌 숫자 키를 사용한 것같은 결과가 초래된다.

let a =[]
a[14]="asa" // 숫자로 index 추가한 경우
a.length //15
a // [empty × 14, "asa"]

let a =[]
a["14"] ="asa" // 10진수 string으로 index를 추가한 경우
a.length // 15
a // [empty × 14, "asa"]

이렇게 유연하면서도 불합리해보이는 방법은 권장되는 방법이 아니다
숫자 인덱스를 써야한다면 배열을 문자 키를 써야한다면 객체를 사용하자

2.1.1 유사배열

유사 배열 값 (숫자 인덱스가 가리키는 값들의 집합)을 진짜 배열로 바꾸고 싶은 때가 더러 있다.

여기서 유사배열이란?

유사배열은 마치 배열같은 객체를 말하며 dom에서 가져온 element들 대표적인 예로 들 수있다.
배열과 유사배열을 판변하는 방법느 Array.isArray()함수 가있다.
만약 dom에서 유사배열을 가져올경우

let a= document.getElementsByClassName("cm-header cm-header-1")
a.forEach() // Error a.forEach is not a function
Array.isArray(a) // false

하지만 유사배열을 배열로 만드는 방법이 있는데

Array.from(yousaArray) 
Array.prototype.slice.call(yousaArray)
[...yousaArray]
// 파라미터를 배열로 받기(...arg) 

function toArrayOne (){
	let array=Array.from(arguments)
	/* OR let Array =Array.prototype.slice(arguments) 이런 케이스가 있다고는 알아두자 */
	return array
}
OR
function toArrayTwo(...arg){
	// ...arg는 매개변수를 array로 받는다
	let array=arg
	return array
}
OR
function toArrayThree(){
	return [...arguments]
}

책에는 펑션에서 argumets를 받아와 Array.prototype.slice.call(arguments)를 통해
유사배열을 배열로 Convert를 한다.

여기서 arguments가 무엇인지 좀더 알아보자

MDN에선 다음과같이 정의한다

arguments 객체는 함수에 전달된 인수에 해당하는 Array 형태의 객체입니다.

여기서 "Array형태"란

"Array 형태"란 arguments가 length 속성과 더불어 0부터 인덱스 된 다른 속성을 가지고 있지만, Array의 forEach, map과 같은 내장 메서드를 가지고 있지 않다는 뜻입니다.

라고 정의한다 음.. 유사배열이라는 뜻인 것 같다
또한 MDN에서도 같은 Convert 방식을 기술하고있다

var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);
var args =Array.from(arguments);

그렇다면 arguments를 쓰는 이유는 무엇일까?

일단 arguments안에 어떤 기능들이 숨겨져있는지 알아보자
arguments를 console.log를 찍어보면 다음과같이 나온다

function asd(){ 
	console.log(arguments)
}
asd("asd","asd")
// Arguments(2) ["asd", "asd", callee: ƒ, Symbol(Symbol.iterator): ƒ]

여기서 callee는 arguments를 가지고있는 함수를 참조한다
여기서 함수의 정보를 알아보거나 재귀시킬 수 있지만
MDN에선 다음과같이 경고한다

경고: ECMAScript 제5판(ES5) 은 엄격 모드 (en-US)에서 arguments.callee()의 사용을 금합니다. function 식(expression)에 이름을 주거나 함수 자체를 호출해야 하는 곳에 function 선언을 사용하여 arguments.callee() 사용을 피하세요.

예를들면(잠시 알고리즘을...)
가령 [1,2,3,4,5,6]이라는 배열이 있고

이배열을
1부터 6까지 각각의 factorial 결과를 내고싶을 때

  index  value   result
    0	    1       1
    1       2       2
    2	    3       6
    3       4       24
    4       5       120

다음과 같이 재귀함수를 써서 표현 할 수 있다.

function factorial (n) {
   return !(n > 1) ? 1 : factorial(n - 1) * n;
  //팩토리얼 함수에서 결과가 1이 될때까지 값을 1씩 빼가면서 곱샘값을 반환한다. 그리고 마지막 * n (초기값) 해준다.
}

[1,2,3,4,5].map(factorial);

하지만 따로 함수를 선언하지 익명함수로 표현을 한다면?

[1,2,3,4,5].map(function (n) {
    return !(n > 1) ? 1 : /* 어떤 함수를 재귀하나? */ (n - 1) * n;
});

때문에

[1,2,3,4,5].map(function (n) {
    return !(n > 1) ? 1 : arguments.callee(n - 1) * n;
});

위와 같은 방법으로
arguments객채를 통해 재귀할수 있다 하지만 이것은 차선책이며

MDN에선 다음과같이 사용을 권장한다.(유명함수를 사용)

[1,2,3,4,5].map(function named (n) {
    return !(n > 1) ? 1 : named(n - 1) * n;
});

이는 다음과같은 이점이 있다

  • 함수는 코드 내부에서 다른 함수처럼 호출될 수 있습니다
  • 외부 범위(outer scope)에서 변수를 만들지 않습니다 (IE 8 아래는 제외하고)
  • arguments 객체에 액세스하는 것보다 성능이 더 낫습니다

결론

arguments.callee 어쩔수없이 익명함수를 써야하고 이 익명함수를 재귀시킬때 사용해야한다.

참조 MDN:arguments.callee


[추가]

또한 arguments 안에는

Symbol(Symbol.iterator): ƒ

을 포함하고 있는데 이는
반복문에 사용할 수 있도록 하는 함수이다. 다음과 같이 사용 할 수 있다.

function f() {

  for (let letter of arguments) {
    console.log(letter);
  }
}
f('w', 'y', 'k', 'o', 'p');
// w
// y
// k
// o
// p

참조 MDN : arguments[@@iterator]()

profile
RN/react.js개발자이며 배운것들을 제가 보기위해서 정리하기 때문에 비속어 오타가 있을수있습니다.

0개의 댓글