모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다.
이것은 마치 객체지향의 상속개념과 같이 부모 객체의 프로퍼티를 마치 자신의 것처럼 쓸 수 있는 것 같은 특징이 있다.
자바스크립트에서는 이러한 부모 객체를 프로토타입 객체(짧게는 프로토타입) 라고 부른다.
var foo = {
name: 'foo',
age: 30
};
console.log(foo.toString()); // [object Object] -----1)
console.dir(foo); // foo 객체 출력 -------2)
1) 앞 예제는 단순히 객체 리터럴 방식으로 foo 객체를 생성하였고 toString() 메서드는 없다. 정상적으로 결과가 나온 이유는 바로 foo 객체의 프로토타입에 toString() 메서드가 이미 정의 되어있고, foo 객체가 상속처럼 toString() 메서드를 호출했기 때문이다.
2) 객체를 출력해보면, name과 age 프로퍼티 외에도 proto 프로퍼티가 있다는 것을 확인할 수 있다. 이 프로퍼티는 foo객체의 부모인 프로토타입 객체를 가리킨다. 이 객체를 펼쳐보면 toString() 메소드가 정의되어있는 것을 알 수 있다.
ECMAScript 명세서에는 자바스크립트의 모든 객체는 자신의 프로토타입을 가리키는 [[Prototype]]라는 숨겨진 프로퍼티를 가진다고 설명하고 있다.
즉, 위에서 foo객체는 자신의 부모 객체를 prototype라는 내부 프로퍼티로 연결하고 있는 것이다.
모든 객체의 프로토타입은 자바스크립트의 룰에 따라 객체를 생성할 때 결정되며(프로토타입 체이닝에서 설명) 후에 임의의 다른 객체로 변경하능하다.
객체 리터럴 방식으로 생성된 객체의 경우 Object.prototype 객체(proto)가 프로토타입 객체가 된다는 것을 기억해야한다.
출처 : https://boycoding.tistory.com/16
__proto__에는 toString(), valueOf() 등과 같은 모든 객체에서 호출 가능한 자바스크립트 기본 내장 메서드가 포함되어있다.
배열은 자바스크립트 객체의 한 형태이다.
C나 자바와 같은 기능을 하지만, 크기를 지정하지 않아도 되고 어떤 위치의 어느 타입의 데이터를 저장하더라도 에러가 발생하지 않는다.
배열 리터럴은 자바스크립트에서 새로운 배열을 생성하는 데 사용하는 표기법이다.
var color = ['orange', 'yellow', 'blue', 'green', 'red'];
console.log(color[0]); // orange
console.log(color[4]); // red
배열 리터럴에서는 각 요소의 값만 포함하며, 인덱스로 접근할 수 있다.
배열도 동적으로 배열 원소를 추가할 수 있다.
자바스크립트 배열의 경우는 값을 순차적으로 넣지 않아도 아무 인덱스 위치에나 값을 동적으로 추가할 수 있다.
var emptyArr = [];
console.log(emptyArr[0]); // undefined
emptyArr[1] = 1;
emptyArr[4] = 'four';
emptyArr[5] = true;
console.log(emptyArr); // [undefined, 1, undefined x 2, 'four', true]
자바스크립트 객체에기 때문에 객체에서도 포함하지 않은 객체의 프로퍼티에 접근한 경우 undefined가 출력된 것과 같이 배열의 경우도 값이 없는 원소에 접근할 경우 undefined가 출력된다.
모든 배열은 length 프로퍼티가 있다.
배열의 원소 개수를 나타내지만, 실제로 배열에 존재하는 원소 개수와 일치하는 것은 아니다.
console.log(emptyArr.length); // 6
emptyArr.length = 8;
console.log(emptyArr); // [undefined, 1, undefined x 2, 'four', true, undefined x 2]
length 프로퍼티는 배열 내에 가장 큰 인덱스에 1을 더한 값이며, 배열의 가장 큰 인덱스 값이 변하면, length도 자동으로 바뀐다.
하지만 실제 메모리는 length크기처럼 할당되지는 않는다.
배열의 length 프로퍼티는 코드를 통해 명시적으로 값을 변경할 수도 있다.
값을 증가시키면 undefined가 추가되며, 감소시키면 값이 잘려 출력된다.
자바스크립트는 배열에서 사용 가능한 다양한 표준 메서드를 제공한다.
이러한 메서드들은 length 프로퍼티를 기반으로 동작한다.
예를 들어, push 함수는 length 인덱스에 요소를 추가한다.
자바스크립트에서 배열은 객체라고 하였다.
하지만 배열은 일반 객체와는 약간 차이가 있다.
var colorsArray = ['orange', 'yellow', 'green'];
console.log(colorsArray[1]); // yellow
var colorsObj = {
'0': 'orange',
'1': 'yellow',
'2': 'green'
};
console.log(colorsObj[1]); // yellow ----------1)
// typeof 연산자 비교
console.log(typeof colorsArray); // object ----------2)
console.log(typeof colorObj); // object
// length 프로퍼티
console.log(colorsArray.length); // 3
console.log(colorObj.length); // undefined ----------3)
// 배열 표준 메서드 ----------4)
colorsArray.push('red'); // 됨
colorsObj.push('red'); // Uncaught TypeError: Object #<Object> has no method 'push'
1) 객체 프로퍼티를 접근할 때는 프로퍼티 속성을 문자열 형태로 적어야하지만, 자바스크립트 엔진이 []연산자 내에 숫자가 사용될 경우, 해당 숫자를 자동으로 문자열 형태로 바꿔주기 때문에 에러를 내지 않는다.
2) 배열도 object이다.
3) 객체엔 length 프로퍼티가 존재하지 않는다.
4) 배열과 객체가 자신의 부모인 프로토타입 객체가 서로 다르기 때문에 객체는 push() 메서드가 없어 에러를 출력한다.
배열의 경우 Array.prototype객체가 부모 객체인 프로토타입이 된다.
Array.prototype 객체는 배열에서 사용하는 push(), pop() 등과 같은 표준 메서드를 포함하고 있다.
Array.prototype 객체의 프로토타입은 Object.prototype 객체이다.
출처 : https://boycoding.tistory.com/16
캡쳐에 있는 Array[0] 객체가 바로 Array.prototype 객체를 나타낸다.
그리고 Array.prototype 객체 역시 __proto__프로퍼티를 가지고 있는데, 이 값은 Object.prototype을 가리킨다.
배열도 자바스크립트 객체이므로, 인덱스가 숫자인 배열 원소 이외에도 'name', 'age'와 같은 프로퍼티들을 동적으로 추가할 수 있다.
var arr = ['zero','one','two'];
arr.color = 'blue';
arr.name = 'number_array';
console.log(arr.legnth); // 3
프로퍼티를 추가한다고 length값이 바뀌지는 않는다.
배열의 length 프로퍼티 배열 원소의 가장 큰 인덱스가 변했을 경우만 변경된다.
객체는 for in 문으로 프로퍼티를 열거할 수 있다.
배열도 객체이므로 for in 문을 사용하여 배열 내의 모든 프로퍼티를 열거할 수 있지만, 이렇게 되면 불필요한 프로퍼티가 출력될 수 있으므로 되도록 for 문을 사용하는 것이 좋다.
for (var prop in arr) {
console.log(prop, arr[prop]);
}
for (var i=0; i<arr.length; i++){
console.log(i, arr[i]);
}
배열도 객체이므로, 배열 요소나 프로퍼티를 삭제하는 데 delete 연산자를 사용할 수 있다.
var arr = ['zero','one','two'];
delete arr[2];
console.log(arr); // ['zero','one',undefined]
console.log(arr.length); // 3
delete 연산자는 해당 요소의 값을 undefined로 설정할 뿐 원소 자체를 삭제하지는 않는다.
때문에 보통 배열에서 요소들을 완전히 삭제할 경우 splice () 배열 메서드를 사용한다.
splice(startIndex, countOfWillingToDelete, item...);
countOfWillingToDelete : startIndex부터 삭제할 요소 수
item : 삭제할 위치에 추가할 요소
var arr = ['zero','one','two'];
arr.splice(1,1);
console.log(arr); // ['zero','two']
console.log(arr.length); // 2
배열은 일반적으로 배열 리터럴로 생성하지만, 배열 리터럴도 결국 자바스크립트 기본 제공 Array () 생성자 함수로 배열을 생성하는 과정을 단순화시킨 것이다.
Array()로 생성하는 방법(new 연산자로 생성)은 간단히 알아두기만 하면 된다.
var foo = new Array(3); // 길이를 넣음
console.log(foo); //[undefined,undefined,undefined]
var bar = new Array(1,2,3);
console.log(bar); //[1,2,3]
foo 배열의 경우는 Array() 생성자 함수를 호출할 때 3이라는 숫자 인자 1개만 넘겼으므로, 길이가 3인 빈 배열을 생성하지만, 반면에 bar는 요소를 지정하여 배열을 생성한다.
배열의 length 프로퍼티는 배열의 동작에 있어서 중요한 프로퍼티이다.
일반 객체에 length라는 프로퍼티가 있으면, 이러한 객체를 유사 배열 객체(array-like objects) 라고 부른다.
이러한 유사 배열 객체의 가장 큰 특징은 객체지만, apply() 메서드를 사용하면 자바스크립트의 표준 배열 메서드(push 등)를 사용하는 게 가능하다.
(그냥 가능하다!정도만 숙지하자)
후에 call과 apply 메서드를 이용한 명시적인 this 바인딩에서 자세히 나올 예정이다.