문제

나는 JavaScript 어레이를 가지고 놀았고, 나는 내가 느끼는 것이 불일치라고 생각합니다. 누군가가 나를 위해 설명 할 수 있기를 바랍니다.

이것으로 시작하겠습니다.


var myArray = [1, 2, 3, 4, 5];
document.write("Length: " + myArray.length + "<br />");
for( var i in myArray){
   document.write( "myArray[" + i + "] = " + myArray[i] + "<br />");
}
document.write(myArray.join(", ") + "<br /><br />");
Length: 5
myArray[0] = 1
myArray[1] = 2
myArray[2] = 3
myArray[3] = 4
myArray[4] = 5
1, 2, 3, 4, 5

이 코드에는 특별한 것이 없지만 JavaScript 배열은 객체이므로 배열에 적절성이 추가 될 수 있습니다. 이러한 적절성이 배열에 추가되는 방식은 나에게 일치하지 않는 것처럼 보입니다.

계속하기 전에 문자열 값이 JavaScript의 숫자 값으로 어떻게 변환되는지 주목하겠습니다.

  • 비어 비어있는 문자열 -> 스트링 또는 nan의 숫자 값

  • 빈 문자열 -> 0

따라서 JavaScript 배열은 객체이므로 다음은 합법적입니다.


myArray["someThing"] = "someThing";
myArray[""] = "Empty String";
myArray["4"] = "four";

for (myArray의 var i) {document.write ( "myArray [" + i + "] =" + myArray [i] + "u003Cbr /> ");} document.write (myArray.join (", ") +"u003Cbr />u003Cbr /> ");

Length: 5
myArray[0] = 1
myArray[1] = 2
myArray[2] = 3
myArray[3] = 4
myArray[4] = four
myArray[someThing] = someThing
myArray[] = Empty String
1, 2, 3, 4, four

출력은 예상치 못한 것입니다.

비 빈 문자열 "4"는 속성 MyArray [ "4"]를 설정할 때 숫자 값으로 변환됩니다. 그러나 빈 문자열 ""은 숫자 값 0으로 변환되지 않으며 빈 문자열로 취급됩니다. 또한 비 빈 문자열 "Something"은 숫자 값 Nan으로 변환되지 않으며 문자열로 취급됩니다. 그래서 그것은 무엇입니까? MyArray [] 내부의 명령문은 숫자 또는 문자열 컨텍스트입니까?

또한 MyArray.length 및 MyArray.join ( ",")에 MyArray의 두 가지가 아닌 두 가지의 적절성이 포함되지 않는 이유는 무엇입니까?

도움이 되었습니까?

해결책

JavaScript 배열의 키는 실제로 문자열입니다. 임의의 키에 대한 자세한 내용 및 맵 유형 구현은 확인하십시오. 이 답변.


Jason이 게시 한 내용을 명확히하고 추가하기 위해 : JavaScript Array는 개체입니다. 객체에는 속성이 있습니다. 속성 이름은 문자열 값입니다. 따라서 배열 지수는 더 많은 일이 발생하기 전에 문자열로 변환됩니다. 속성 이름 P는 다음이 보유 된 경우 (ECMA-262, 15.4)의 경우 배열 인덱스 (즉, 특수 배열 마그 닉이 호출됩니다) : :

Tostring (touint32 (p))는 p와 같고 touint32 (p)는 2^32-1과 같지 않습니다.

숫자 지수는 문자열로 변환 될 것입니다 (주변의 다른 방법이 아님)는 쉽게 확인할 수 있습니다.

var array = [];
array[1] = 'foo';
array['1'] = 'bar';
array['+1'] = 'baz';
document.writeln(array[1]); // outputs bar

또한, 배열의 항목을 반복하는 나쁜 관행은 for..in 루프 - 누군가가 프로토 타입을 엉망으로 만들면 예기치 않은 결과를 얻을 수 있습니다 (실제로 빠르지는 않습니다). 표준을 사용하십시오 for(var i= 0; i < array.length; ++i) 대신에.

다른 팁

(편집 : 다음은 옳지 않습니다)

JavaScript의 키 물체 실제로 문자열입니다. 자바 스크립트 정렬 그 자체로는 숫자 지수가 있습니다. 음이 아닌 정수로 해석 될 수있는 색인으로 무언가를 저장하면 그렇게하려고합니다. 음이 아닌 정수가 아닌 색인으로 무언가를 저장하는 경우 (예 : 영숫자, 음수 또는 분수 조각이있는 부동 소수점 번호) 배열 인덱스 저장소에서 실패하고 기본값이 발생합니다. 물체 (배열의 기본 클래스) 스토어를 문자열로 변환하고 문자열 인덱스로 인수를 변환하지만이 저장된 속성은 배열 클래스에서 보이지 않으므로 메소드/속성 (길이, 조인, 조인, 조인)에는 보이지 않습니다. 슬라이스, 스플 라이스, 푸시, 팝 등).

편집 : 위의 것은 옳지 않습니다 (Christopher의 foo/bar/baz 예제가 보여준 것처럼). 실제 저장 지수에 따라 ecmascript 사양 실제로 문자열이지만 유효한 배열 지수 (음이 아닌 정수) 인 경우 배열 객체의 경우 [[Put]] 특별한 방법은 해당 특정 값이 배열의 "배열 -Ish"메소드에 보이게 만듭니다.

이것은 답입니다 Philo의 게시물. 그의 벤치 마크는 객체 버전에 다른 속성 이름을 사용하기 때문에 결함이 있습니다. i 뿐만 아니라 x.

예를 들어 다음과 같이 올바르게 수행하면 :

var start, end, count = 1000000;

var obj = {},
    array = [];

start = new Date;
for(var i = count; i--; )
    array[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));

start = new Date;
for(var i = count; i--; )
    obj[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));

시간이 매우 가까울 것임을 알 수 있습니다. FF3.0.5에서 배열 버전은 일관되게 느리게 진행됩니다 (오페라에서는 다른 방법입니다).

JavaScript의 다른 모든 것들과 마찬가지로 배열은 객체입니다. 물체는 축복을 받았습니다 도트 표기법 개발자에게 부담을 줄입니다. 예제를 사용합니다

myArray["someThing"] = "someThing";

글쓰기와 동일합니다

myArray.someThing = "someThing";

이 경우 배열에 추가하는 대신 객체에 속성을 추가합니다. 사용 할 수는 없지만 빈 문자열도 마찬가지입니다. 도트 표기법 빈 끈의 경우 ... 이상하게?

"4"의 경우 정수로 강요 될 수 있으므로 배열의 색인으로 사용됩니다.

나는 Christoph가 "배열 지수가 문자열로 변환된다"고 말할 때 동의하지 않습니다.

첫째, 구현 의존적이라고 생각합니다 ... (좋은) 구현자가 배열 액세스를 최적화 할 것이라고 생각합니다.

실제로, 나는 약간의 테스트를했고, 대부분의 마이크로 벤치 마크 (즉, 매우 신뢰할 수 없음)만큼 우수하지만 흥미 롭습니다.

result = ""
var x;

var trueArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
  x = "i" + i; // To do the same operations
  trueArray[i] = 1;
}
var endTime = new Date();
result += "With array: " + (endTime - startTime) + "\n";

var sArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
  x = "" + i;
  sArray[x] = 1;
}
var endTime = new Date();
result += "With s array: " + (endTime - startTime) + "\n";

var objArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
  x = "i" + i;
  objArray[x] = 1;
}
var endTime = new Date();
result += "With object(i): " + (endTime - startTime) + "\n";

var sobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
  x = "" + i;
  sobjArray[x] = 1;
}
var endTime = new Date();
result += "With s object: " + (endTime - startTime) + "\n";

var iobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
  x = "" + i;
  iobjArray[i] = 1;
}
var endTime = new Date();
result += "With i object: " + (endTime - startTime) + "\n";


// Then display result

IE6에서 나는 얻을 수있다 : 배열 : 1453 with 객체 : 3547
FF 3.0에서 나는 얻을 수있다 : 배열 : 83 객체 : 226
Safari 3.1에서, 나는 얻을 수있다 : 배열 : 140 객체 : 313
Opera 9.26에서 어떤 이유로 든 결과를 얻지 못하지만 루프 수의 10 분의 1로 줄어든다면 : 배열 : 47 객체 : 516
실제로, 나는 이것을 입력하는 동안 오페라를 실행하고 마침내 결과를 얻었습니다 : 배열 : 281 with 객체 : 166063 ...

따라서 배열이 최적화됩니다! 운이 좋다 ...
Christoph의 시위는 나를 감동시키지 못했습니다. 나의 결론은 숫자로 해석 될 수있는 문자열이 그러한 것으로 취급되며 인용 된 공식과 함께 진행되는 것입니다 ...

따라서 결과에 대한 나의 해석은 배열이 이들 (희소 한 값에 대한 연관 배열의 동작, 즉 일부 분리 된 큰 지수)가있는 숫자 지수가있는 빠른 배열처럼 작동한다는 것입니다. 속성의 정상적인 처리가 있습니다. 그러나 이러한 속성은 배열 부분에서 처리되지 않으므로 join ()로 얻은 결과입니다.

편집] Christoph의 아이디어에 따라 약간의 루프를 추가했습니다.
FF3에서 : 배열 : 92가있는 S array : 93 객체 (i) : 243 S 객체 : 194 with I object : 125 (성능은 런마다 다르지만 대략 일관성).

나는이 정수 -> 문자열 -> 정수 왕복 트립에 대해 초조하지 않습니다. 내가 읽는 방식은 다음과 같습니다. 속성은 문자열이며 정수로 해석 될 수 있다는 것입니다.

물론, 알 수있는 유일한 방법은 구현을 보는 것입니다 ...

나는 정수 속성이나 정수로 변형 될 수있는 속성을 얻는 일반 물체가 어떻게 든 최적화되어 있음을 알 수 있습니다. 아마도 많은 JS 프로그래머가 일반 객체를 배열로 사용했기 때문에 구현자는이 사례를 최적화하기 위해 흥미롭게 판단했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top