객체 인 것처럼 명명 된 속성을 배열에 추가 할 수있는 이유는 무엇입니까?


105

다음 두 가지 코드 스 니펫은 나에게 동일하게 보입니다.

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

var myObject = {'A': 'Athens', 'B':'Berlin'};

둘 다 동일하게 행동하기 때문에 typeof(myArray) == typeof(myObjects)(둘 다 '객체'를 산출합니다).

이 변종들간에 차이점이 있습니까?

답변:


131

자바 스크립트의 거의 모든 것이 객체이므로 임의의 속성을 설정 하여 Array 객체를 "남용"할 수 있습니다 . 그러나 이것은 해로운 것으로 간주되어야합니다 . 배열은 숫자 인덱스 데이터 용입니다. 숫자가 아닌 키의 경우 Object를 사용합니다.

다음은 숫자가 아닌 키가 배열에 맞지 않는보다 구체적인 예입니다.

var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";

alert(myArray.length);

이것은 '2'를 표시하지 않지만 '0'을 표시합니다. 사실상 배열에 요소가 추가되지 않고 배열 객체에 몇 가지 새로운 속성이 추가됩니다.


4
myArray.length는 배열의 마지막 요소에 대한 숫자 인덱스 / 키를 반환하지만 실제 요소 수는 반환하지 않습니다. Array 객체의 속성이 배열 값과 동일하지 않습니까?
Dasha Salo

1
그냥 일반 객체처럼 취급하면 Array 객체의 의도 된 의미가 남용된다는 것을 설명하려고했습니다. 링크 된 기사는 더 나은 작업을 수행합니다. :)
Paul Dixon

13
다음에 누군가 JavaScript가 개발하기에 좋은 언어라고 말할 때이 샘플을 보여 드리겠습니다. 감사합니다.
Olivier Pons 2014

@Olivier, "버그"라고 부르는 것도 멋진 "기능"이 될 수 있습니다. 배열의 내용이나 길이에 영향을주지 않고 title, descriptionitems속성을 사용 하여 객체로 래핑하지 않고도 배열에 제목과 설명을 추가 할 수 있습니다 . 그것은 모두 당신이 언어를 얼마나 잘 알고 그것을 어떻게 사용하는지에 달려 있습니다.
tao

배열에서 사용자 지정 속성을 사용하는 것은 본질적으로 잘못된 것은 아닙니다. 잘못된 것은 일단 수행하면 배열 구성원으로 작동 할 것으로 예상하는 것입니다. 멤버가 아닌 배열 속성이므로 배열 메서드의 영향을받지 않습니다. 이것은 실제로 위의 링크 된 기사의 작성자가 의견에서 말했습니다. 이제 공정하게 말해서, 나는 당신의 코드를 사용하는 사람들을 혼란스럽게 할 것이기 때문에 실천으로 반대 할 것을 권합니다. 또는 그들이 막 시작하는 경우, 모범의 힘으로 위험한 길에 놓일 것입니다. 하지만 자바 스크립트가 나쁘다고 말하지는 않을 것입니다. 왜냐하면 대부분의 사람들이 허용하지 않을 것으로 예상되는 것을 허용하기 때문입니다.
tao

14

JS 배열에서 객체는 약간 수정 된 것입니다 (몇 가지 추가 기능 포함).

다음과 같은 기능 :

concat
every   
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf 

나열된 모든 함수가 모든 JS 구현에 내장되어 있다고 생각하지는 않지만 요점은 있습니다. 다른 차이점은 다른 프로토 타입 (추가 기능에 의해 암시 됨)입니다.
Rashack

6

나는 이전 답변에 대해 너무 은유적이고 비밀 스럽습니다. 설명은 다음과 같습니다.

Array, Boolean, Date, Function, Number, RegExp, String의 인스턴스는 Object이지만 각 유형에 특정한 메서드와 속성으로 향상되었습니다. 예를 들어, 배열에는 미리 정의 된 length속성이 있지만 일반 객체에는 없습니다.

javascript:alert([].length+'\n'+{}.length)

디스플레이

0
찾으시는 주소가 없습니다

본질적으로 FF Gecko 인터프리터는 언어 구성을 평가하는 뚜렷한 차이점을 가지고 배열과 일반 객체를 구별합니다.

javascript:
  ra=[  "one",   "two",   "three"]; ra.a=4;
  ob={0:"one", 1:"two", 2:"three"}; ob.a=4;
  alert(
    ra            +"\n\n"+
    ob            +"\n\n"+
    ra.toSource() +"\n\n"+
    ra.a          +"\t .toSource() forgot me! \n\n"+
    ra.length     +"\t and my length! \n\n"+
    ob.toSource());
  ps=""; for(i in ra)ps+=i+" "; alert(ps);  /* NB .length is missing! */
  ps=""; for(i in ob)ps+=i+" "; alert(ps);

표시

하나 둘 셋

[객체 객체]

["하나 둘 셋"]

4 .toSource ()가 나를 잊었습니다! 

3 그리고 내 길이! 

({0 : "one", 1 : "two", 2 : "three", a : 4})

0 1 2 a0 1 2 a.

모든 객체가 함수라는 진술과 관련하여 :

이것은 어느 구문이나 의미처럼 정확한 함수로서 임의의 객체 인스턴스를 사용하는 것 123()또는 "abc"()또는 []()또는 {}()또는 obj()여기서 obj이외의 타입이 Function임의의 객체 인스턴스가되지 않도록, Function. 그러나, 객체 부여 obj하고 그것의 유형은 Array, Boolean, Date, ...어떻게 않았다 obj로로 올 Array, Boolean, Date, ...? 무엇입니까 Array, Boolean, Date, ...?

javascript:
    alert([Array, Boolean, Date, Function, 
              Number, Object, RegExp, String] . join('\n\n') );

디스플레이

function Array() {
    [native code]
}

function Boolean() {
    [native code]
}

function Date() {
    [native code]
}

function Function() {
    [native code]
}

function Number() {
    [native code]
}

function Object() {
    [native code]
}

function RegExp() {
    [native code]
}

function String() {
    [native code]
}

모든 경우에 모호하지 않고 객체 유형은 function정의 로 나타나 므로 모든 객체가 함수라는 진술입니다! (혀로 뺨을 치는 것은 내가 의도적으로 객체 인스턴스의 구분을 해당 유형의 구분으로 모호하게 숨기고 흐리게했다는 것입니다. 그래도 이것은 "다른 하나 없이는 가질 수 없습니다"를 보여줍니다. 객체 및 함수! 대문자는 다음과 같이 유형을 강조합니다. 인스턴스에 반대.)

두 기능 및 객체 패러다임은 낮은 수준의 통역 프로그래밍의 기초와 JS의 구현 것 같다 내장 프리미티브, 같은 MathJSONtrue.

 javascript:alert([Math, JSON, true.toSource()].join("\n\n"));

디스플레이

[object Math]

[object JSON]

(new Boolean(true))

자바 스크립트를 개발할 때 객체 중심 프로그래밍 스타일 (OOP-객체 지향 프로그래밍 스타일- " 's"는 내 말장난입니다!)이 유행했고 인터프리터는 더 큰 신뢰성을 제공하기 위해 Java로 비슷한 이름을 붙였습니다. . 함수형 프로그래밍 기술은 Automata, Recursive Functions, Formal Languages ​​등의 이론을 연구하는 좀 더 추상적이고 난해한 시험으로 강등되었으며 그다지 맛이 좋지 않았습니다. 그러나 이러한 공식적인 고려 사항의 강점은 특히 FF의 Gecko 엔진 (예 :)에 구현 된 Javascript에서 명확하게 나타납니다 .toSource().


함수에 대한 객체 정의는 반복 관계로 정의되어 특히 만족 스럽습니다! 자체 정의를 사용하여 정의!

function Function() { [native code] }
그리고 함수는 객체이기 때문에
function Object() { [native code] }.

대부분의 다른 정의는 정적 터미널 값으로 중지됩니다. 그러나 eval()는 특히 강력한 기본 요소이므로 String은 임의의 기능을 포함 할 수도 있습니다.

위에서 사용 된 언어는 객체 유형과 인스턴스 구분을 모호하게합니다.


5

JavaScript의 모든 것은 기본 유형 외에 객체입니다.

코드

var myArray = Array();

Array 객체의 인스턴스를 만드는 동안

var myObject = {'A': 'Athens', 'B':'Berlin'};

Object 개체의 인스턴스를 만듭니다.

다음 코드를 시도하십시오

alert(myArray.constructor)
alert(myObject.constructor)

따라서 객체 생성자의 유형에 차이가 있음을 알 수 있습니다.

Array 객체의 인스턴스에는 Array 프로토 타입의 모든 속성과 메서드가 포함됩니다.


2

자바 스크립트에서 배열과 다른 객체의 차이. 배열에는 마술처럼 업데이트되는 길이 속성이 있지만 배열이 아닌 다른 객체의 경우 이러한 속성을 구현할 방법이 없습니다.

var arrName = [];
arrName[5] = "test";
arrName.length; // <- 6

배열은 서수 색인으로 사물을 저장하는 데 사용됩니다. 기존 배열, 스택 또는 대기열처럼 사용합니다. 객체는 해시입니다. 고유 한 키가있는 데이터에 사용합니다.


2

자바 스크립트의 거의 모든 것에 명명 된 속성을 추가 할 수 있지만 그렇다고해서 그렇게해야한다는 의미는 아닙니다. 대신 Array연관 배열을 사용하려면 자바 스크립트에서 목록으로 사용해야 Object합니다.

실제로 이러한 Array속성 대신 명명 된 속성 을 사용하려는 경우 루프 Object에서 액세스 할 수 없으며 for...ofJSON 인코딩을 통해 전달할 때 예기치 않은 결과가 발생할 수도 있습니다. 숫자가 아닌 모든 색인이 무시 되는 아래 예를 참조하세요 .

let arr = [];
let obj = {};

arr['name'] = 'John';
obj['name'] = 'John';

console.log(arr);    // will output [name: "John"]
console.log(obj);    // will output {name: "John"}

JSON.stringify(arr); // will return [] <- not what you expected
JSON.stringify(obj); // will return {"name":"John"}

-1

- {}표기법은 코드를 더 멋지게 만들기위한 구문 적 설탕 일뿐입니다 ;-)

JavaScript에는 함수 구성과 같은 유사한 구조가 많이 있습니다. 여기서 function ()은

var Func = new Function("<params>", "<code>");

3
함수 생성자는 함수 리터럴의 동의어 가 아닙니다 . 생성자가 전역 인 동안 리터럴은 어휘 범위가 지정됩니다. {}리터럴 객체 표기법이고 []리터럴 배열입니다. 대답의 요점이 무엇인지 잘 모르겠습니다.
Juan Mendes 2011

또한 선언 된 함수는 코드가 실행되기 전에 사용할 수 있으며 Function 생성자를 사용한 할당은이를 생성하는 코드가 실행될 때까지 사용할 수 없습니다.
RobG 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.