반응형

<프로토타입이 뭔지 알기 위해 먼저 알아야 할 것들>

1. 생성자 함수와 인스턴스

1. 생성자 함수 : 객체를 생성하는 함수이다.

function SomeObj(name, kind) { this.name = name; // 변수 정의 this.kind = kind; this.someFunction = function() { // 함수 정의 alert(this.name + this.kind) }; }; // 자바스크립트에서는 이런식으로 객체를 생성한다. 이제 이 SomeObj함수를 사용하면 객체를 만들 수 있다.

 

 

2. 인스턴스 : 정의되어 있는 클래스를 실제 사용하기 위해 new연산자를 통해 메모리상에 객체를 구현한 것

1. var obj = new SomeObj('abc', 'killer') 라고 하면 위에서 정의한 클래스를 토대로 메모리상에 obj라는 객체를 구현한다.

 

2. 여기서 obj를 인스턴스라고 하고, SomeObj를 생성자함수라고 한다.

 

 

 

이제 프로토타입에 대해서 알아보자

1. 프로토타입이란?

1. 자바스크립트는 함수가 만들어지면 그 함수에 자동으로 prototype(이하 프로토타입) 프로퍼티를 생성한다. (여기서 프로퍼티란 그냥 멤버필드 혹은 자원이라고 생각하면 된다.)

 

2. 즉 내가 위에서 SomeObj를 정의한 순간 prototype도 같이 안에 만들어져진다. 이건 내가 만드는게 아니라 자바스크립트가 내부에서 자동으로 만드는 것이다.

 

3. var obj = new SomeObj('leeNOW', 'femmeFatale') 하는 순간 obj에 객체가 생성되면서 obj인스턴스가 생성된다.

 

4. 그리고 이 때 obj인스턴스 안에 자동적으로 __proto__(이하 던더프로토)가 생성되고 생성자의 프로토타입을 참조한다.

 

5. 던더프로토는 생성자의 프로토타입을 참조하기때문에 프로토타입 안에 있는 자원을 그대로 사용할 수 있다.

 

6. SomeObj.prototype.anyFunction = function() {} 이런식으로 생성자의 프로토타입안에 자원을 추가할 수 있다.

 

7. 프로토타입안에 있는 것은 던더프로토 안에도 있기 때문에 인스터스생성시 obj.__proto__.anyFuntion() 이렇게 사용할수 있다.

 

8. 그러나 __proto__는 생략가능하기 때문에 우리는 바로 obj.anyFunction() 이렇게 사용할 수 있다.

 

9. 결론적으로 생성자의 프로토타입에서 정의된것은 그 생성자로 만들어진 인스턴스의 던더프로토안에도 정의되어 있다.

 

10. 배열생성자함수인 Array와 그 인스턴스 arr의 예를 보면서 다시 한 번 이해 및 정리해보자

 

// 브라우저를 키고 개발자모드에서 다음 코드를 쳐보자. var arr = [1,2]; console.dir(arr); console.dir(Array); // arr, Array의 던더프로토와 프로토타입을 서로 비교해보자 완전히 같음을 알 수 있다. // arr의 던더프로토가 Array의 프로토타입을 참조하기 때문이다. // 따라서 arr의 던더프로토를 이용하여 생성자함수의 프로토타입에 정의된 모든 자원을 활용 할 수 있다. arr.__proto__.pop(); // 하지만 이렇게 하면 예상치 못한 결과가 나올 경우가 있다. // 그 이유는 this를 사용한 코드가 있으면 this가 가르키는 곳이 의도했던것과 달라지기 때문이다. // __proto__는 생략가능하므로, 이렇게 쓰자 arr.pop(); 이게 우리가 흔히 쓰던 사용법일 것이다. // 또한 Array생성자 바로 밑에 있는 자원은 프로토타입에 있지 않기 때문에 직접 불러서 써야한다. Array.isArray(arr); // 이런식으로 직접 생성자 함수를 불러다가 써줘야한다. // 이제 당신은 어떤 함수는 인스턴스에다 직접 써도 되고 (생성자함수의 프로토타입안에 있는 자원들) // 어떤함수는 생성자함수를 불러다가 써줘야하는지 알게된 것이다. (생성자함수 안에 있는 자원들)

 

 

 

 

 

*틀린 점이 있다면 댓글로 달아주세요. 아직 배우는 학생이랍니다.

*질문도 댓글로 적어주시면 답변할 수 있는 한도내에서 답변해드리겠습니다.

감사합니다. "쿠쿠하마"입니다.

반응형
반응형

자바스크립트를 초반에 배울 때는 참조형 데이터는 메모리 주소값이 저장되고, 기본형 데이터는 값이 직접 저장된다고 배우지만 사실은 다르다.

 

자바스크립트에서 모든 데이터는 참조형 데이터처럼 주소값이 저장된다.

 

var a = 0

1. 메모리 어딘가에 0이란 데이터가 있는 먼저, 찾아본다. 그리고 어디에도 0이란 데이터가 저장되어 있지 않다면 0이란 데이터를 임의의 메모리 공간에 저장하고 해당 메모리 주소값을 기억한다.

 

2. a라는 식별자를 어떤 임의의 메모리 공간에 “이름표”로써 저장한다 (나중에 컴퓨터가 a를 찾게되면 이름이a인 이 메모리 공간으로 오게된다.)

 

3. 그리고 a라는 이름을 가진 메모리 공간의 값으로 1번에서 기억했던 메모리 주소값을 저장한다.

 

4. 이렇게 a의 공간의 값에 바로 0이 저장되는게 아니라, 0은 다른 어딘가에 저장되어 있고 해당 주소값을 a의 값으로 저장한다.

 

5. 이렇게 모든 자바스크립트 데이터는 참조방식으로 저장이된다.

 

1번에 대한 추가 설명) 변수를 선언하고 어떤 데이터를 할당할 때, 메모리의 효율성 때문에 자바스크립트는 데이터를 재활용하기 위해 먼저 기존 메모리에 같은 데이터가 이미 저장되어 있는지 확인한다. 그리고 해당 데이터가 이미 존재 한다면, 굳이 새로 공간을 파지 않고 기존에 있던 공간의 메모리 주소값을 준다.

 

 

2번에 대한 추가 설명) “이름표”이란 표현이 이해가 잘 안 될 수도 있다. 나도 그렇다. 다만 나는 이렇게 생각하고 있다.

 

1. 모든 메모리의 공간은 각각의 메모리 주소값을 가진다. 그리고 이건 보통 16진수로 표현된다.

 

2. 우리는 메모리에 어떤 데이터를 저장하고 싶을 때 변수를 선언해서 데이터를 할당한다.

 

3. 근데 만약 변수라는 개념이 없어도 메모리에 데이터를 저장 할 수 있을까? >> 할 수 있다. 직접 메모리의 주소값을 쓰면된다. 하지만 어렵고 기억하기도 힘들다.

 

4. 따라서 원할한 프로그래밍 개발을 위해 변수라는 개념이 필요했다.

 

5. 변수를 선언하게 되면 내부적으로 어떤 원리에의해 메모리의 임의의 공간에 대한 이름표로써, 식별자를 붙여준다.

 

6. 여기서 이 식별자가 바로 사용자가 정한 변수명이다.

 

7. 다시 정리해보면 개발자가 변수를 선언하면 컴퓨터는 임의의 메모리 공간에 이름표(사용자가 정한 변수명)를 붙이고, 그 공간에 값을 저장 할 수 있다. 그리고 그 값으로 무조건 주소값이 오게된다.(=자바스크립트 데이터는 참조 타입으로 저장된다.)

 

 

7번에 대해 추가 설명) 메모리에 변수로 쓰일 공간과, 데이터( =실제 값)가 저장될 공간은 서로 분리되어 저장된다. 이는 효율성과 안정성을 위함으로 보인다.

 

1. 변수가 저장될 공간은 공간이 그리 많이 필요하지 않다. 이름표로써 식별자(변수명)가 붙을 공간과 그 값으로 메모리 주소값인16진수만 저장되면 되기 때문이다.

 

2. 하지만 데이터가 저장될 공간은 가변적이다. 개발자가 언제 어떤 데이터를 넣을지 모르기 때문이다.

 

3. 만약 변수가 저장될 공간과 데이터가 저장될 공간이 분리되지 않고, 같은 공간에 저장된다고 치고 변수가 저장되는 과정을 다시 살펴보자

 

4. var a = 10; //이러면 컴퓨터는 메모리 임의의 공간에 식별자a로써 이름표를 붙이고 그 값에 10을 할당한다.

(참고로 자바스크립트는 숫자형 데이터를 저장할 때 무조건 64비트 공간으로 할당한다.)

 

5. 그리고 나는 또 변수가 필요해서 하나 더 선언하고 값을 할당했다. var b = 20; 그런데 우연히도 메모리에서 데이터의 저장 위치가 a의 저장공간 바로 옆에 딱 붙어서 b가 저장되었다고 가정하자 (메모리의 공간이 부족해서 자리가 여기밖에없다면 이렇게 할 수 밖에 없을 것이다.)

 

6. 그런데 나는 변수 a의 데이터를 숫자가 아닌 커다란 객체를 담게 될 필요가 생겼다.

 

7. 여기서 부터 문제가 발생한다. a의 크기는 64비트이다. 그 이상의 데이터를 담을려면 공간이 옆으로 확장되어야 하는데, 우연치않게 바로 옆에 변수 b의 공간을 침범해야 하기 때문이다. 이렇게 되면 결국 내부적으로 컴퓨터는 변수 b를 다시 다른 곳으로 옮기고 a의 크기를 조절해야한다. 그리고 다시 그 옆에다 b를 할당한다.

 

8. 이렇게되면 도미노 현상처럼 내부적으로 메모리들의 많은 공간이 재배치되고 그에 따라 식별자 '이름표'도 다시 재배치된다. 이것은 효율성과 안정성에 문제가 될 것이다.

 

9. 문제의 원인은 변수와는 달리, 가변성이 큰 데이터에 있다. 따라서 데이터를 담을 공간을 변수와 분리시켜 저장하는 것이다.

 

10. 이렇게 분리하면 데이터를 저장하는 공간만(변수 공간은 건드릴 필요없다.) 크기를 조절하고 그에 대해 메모리 위치가 변경되었다면 바뀐 주소값만 해당 변수의 값에다 교체만 해주면 되기 때문이다.

 

11. 10에서도 도미노 현상은 완전히 막을 수는 없지만 이렇게 공간을 분리시켜 저장하는게 그나마 상대적으로 더 효율적이다.

 

 

 

 

 

*틀린 점이 있다면 댓글로 달아주세요. 아직 배우는 학생이랍니다.

*질문도 댓글로 적어주시면 답변할 수 있는 한도내에서 답변해드리겠습니다.

감사합니다. "쿠쿠하마"입니다.

반응형

'javaScript > 중급' 카테고리의 다른 글

프로토타입(prototype, __proto__)  (0) 2020.06.22

+ Recent posts