JavaScript에서 프로토 타입 프로그래밍을 사용하는 경우


15

나는 다음과 같은 방법으로 프로젝트를위한 간단한 위젯을 개발하는 데 많은 시간을 보냈습니다.

var project = project || {};

(function() {

  project.elements = {
    prop1: val1,
    prop2: val2
  }

  project.method1 = function(val) {
    // Do this
  }

  project.method2 = function(val) {
    // Do that
  }

  project.init = function() {
    project.method1(project.elements.prop1)
    project.method2(project.elements.prop2)
  }
})()

project.init();

그러나 형식을 다음과 같이 변경하기 시작했습니다.

function Project() {
  this.elements = {
    prop1: val1,
    prop2: val2
  }

  this.method_one(this.elements.prop1);
  this.method_two(this.elements.prop2);
}

Project.prototype.method_one = function (val) {
  // 
};

Project.prototype.method_two = function (val) {
  //
};

new Project();

물론, 이것은 바보 같은 예이므로 악셀 주위를 감싸지 마십시오. 그러나 기능상의 차이점은 무엇이며 언제 하나를 선택해야합니까?


프로젝트가 범위를 벗어나지 않으므로 첫 번째 코드 예제가 작동하지 않는다고 생각합니다. JS에서 상속을 사용하려면 프로토 타이핑을 사용하십시오. 첫 번째 예는 프로젝트를 확장하기위한 것이 아니므로 재사용 성이 제한 될 수 있습니다.
Aitch

네, 실수로 project선언문을 함수 안에 넣었습니다 . 업데이트되었습니다.
JDillon522

여기에서도 마찬가지입니다. 첫 번째 예제는 정적이고 두 번째 예제는 객체 지향입니다.
Aitch

1
하나의 객체 인스턴스 만 사용하는 경우 프로토 타입 정의를 사용할 이유가 없습니다. 그리고 당신이 필요로하는 것-모듈 형식입니다-많은 옵션이 있습니다. addyosmani.com/writing-modular-js
c69

1
싱글 톤 패턴을 위한 첫번째 것 싱글 톤 이 아닌 것을위한 두번째 것 (1 개의 클래스가 많은 물건을 가질 수있는 경우)
Kokizzu

답변:


6

첫 번째 차이점은 다음과 같이 요약 할 수 있습니다 . 클래스 this인스턴스 를 나타냅니다 . 정의를prototype 참조하십시오 .

다음과 같은 클래스가 있다고 가정 해 봅시다.

var Flight = function ( number ) { this.number = number; };

그래서 우리는 this.number클래스의 모든 인스턴스에 연결 하고 있으며, Flight모두 자신의 항공편 번호를 가져야 하기 때문에 의미 가 있습니다.

var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );

반대로 prototype모든 인스턴스가 액세스 할 수있는 단일 속성을 정의합니다.

이제 항공편 번호를 얻으려면 다음 스 니펫을 작성하면 모든 인스턴스가 새로 프로토 타입 된 객체에 대한 참조 를 얻게됩니다 .

Flight.prototype.getNumber = function () { return this.number; };

두 번째 차이점은 JavaScript가 객체의 속성을 검색하는 방식에 관한 것입니다. 를 찾으면 Object.whateverJavaScript는 기본 Object 객체 (다른 모든 것이 상속받은 객체) 까지 올라가고 일치하는 항목을 찾으면 즉시 반환하거나 호출합니다.

그러나 이는 프로토 타입 속성에 대해서만 발생합니다. 따라서 더 높은 계층의 어딘가에 있으면 this.whateverJavaScript는이를 일치 항목으로 간주하지 않고 검색을 계속합니다.

그것이 실제로 어떻게 일어나는지 봅시다.

먼저 [거의] 모든 것이 JavaScript의 객체 라는 점에 유의하십시오 . 이 시도:

typeof null

이제 내부에 무엇이 있는지 살펴 봅시다 Object(대문자 O.끝에 주의하십시오 ). Chrome 개발자 도구를 입력하면 .해당 특정 개체 내에서 사용 가능한 속성 목록이 표시됩니다.

Object.

이제 동일한 작업을 수행하십시오 Function.

Function.

name방법을 알 수 있습니다 . 그냥 가서 해고하면 어떻게되는지 보자.

Object.name
Function.name

이제 함수를 만들어 봅시다 :

var myFunc = function () {};

그리고 우리가 name여기 에 방법 을 가지고 있는지 보자 .

myFunc.name

빈 문자열을 가져와야하지만 괜찮습니다. 오류나 예외가 발생하지 않아야합니다.

이제 그 신과 비슷한 것을 추가하고 Object다른 곳에서도 얻을 수 있습니까?

Object.prototype.test = "Okay!";

그리고 당신은 간다 :

Object.prototype.test
Function.prototype.test
myFunc.prototype.test

모든 경우에을 참조하십시오 "Okay!".

각 방법의 장단점에 대해 프로토 타이핑은 작업을 수행하는 "보다 효율적인"방법으로 간주 할 수 있습니다. 각 객체의 전체 속성을 복사하는 것이 아니라 모든 인스턴스에 대한 참조를 유지하기 때문입니다. 다른 한편으로, 이것은 Tightly Coupling 의 예이며 , 그 이유를 실제로 정당화 할 수있을 때까지는 절대 아닙니다. this문맥과 관련이 있기 때문에 훨씬 더 복잡합니다. 인터넷에서 무료로 좋은 자료를 많이 찾을 수 있습니다.

모두가 말했듯이, 두 가지 방법 모두 언어 도구 일 뿐이며 실제로 당신과 더 잘 맞는 것을 선택하기 위해 해결하려는 문제에 달려 있습니다.

클래스의 모든 인스턴스와 관련이있는 속성이 필요한 경우을 사용하십시오 this. 모든 인스턴스에서 동일한 기능을 수행하기 위해 속성이 필요한 경우을 사용하십시오 prototype.

최신 정보

샘플 스 니펫과 관련하여 첫 번째는 Singleton 의 예 이므로 this객체 본문 내 에서 사용하는 것이 좋습니다 . 모듈 식으로 만들어서 예제를 개선 할 수도 있습니다 (항상 사용할 필요는 없습니다 this).

/* Assuming it will run in a web browser */
(function (window) {
    window.myApp = {
        ...
    }
})( window );

/* And in other pages ... */
(function (myApp) {
    myApp.Module = {
        ...
    }
})( myApp );

/* And if you prefer Encapsulation */
(function (myApp) {
    myApp.Module = {
         "foo": "Foo",
         "bar": function ( string ) {
             return string;
         },
         return {
             "foor": foo,
             "bar": bar
         }
    }
})( myApp );

두 번째 스 니펫은 먼저 사용 this하고 나중에 해킹하려고 시도하기 때문에 그다지 의미 prototype가 없습니다 . this우선 순위가 높아서 작동하지 않습니다 prototype. 해당 코드에서 기대하는 것이 무엇이며 어떻게 작동했는지 잘 모르겠지만 리팩토링하는 것이 좋습니다.

최신 정보

this우선 순위 를 정하기 prototype위해 예제를 보여주고 설명 할 수있는 방법을 알려줄 수 있지만 백업 할 외부 리소스는 없습니다.

예는 매우 간단합니다.

var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";

var obj = new myClass;
obj.foo;     // Still contains "Foo" ...
obj.bar;     // Contains "Bar" as expected

우리가 알고 있듯이 설명은 this상황과 관련이 있습니다. 따라서 컨텍스트가 준비 될 때까지 존재하지 않습니다. 문맥이 준비되면? 새 인스턴스가 생성 될 때! 나머지는 지금 추측해야합니다! 그것은 prototype정의가 있지만 this그 순간에 생성되는 새로운 인스턴스에 관한 것이기 때문에 우선권을 갖는 것이 더 의미가 있음을 의미합니다.


이것은 부분적으로 서사시 멋진 답변입니다! 두 가지 방법을 비교하고 대조하여 편집하고 더 자세히 설명 할 수 있습니까? 처음 두 단락은 어떤 설계 방법을 언급하고 있는지 혼동합니다. 운동이 훌륭합니다! 그런 프로토 타이핑의 힘에 대해서는 전혀 생각하지 않았습니다. 각 방법을 언제 사용해야하는지에 대한 자세한 사례 사용 사례를 제공 할 수 있습니까? 다시 한 번 감사드립니다.
JDillon522

@ JDillon522 다행입니다. 다음 시간에 업데이트하려고합니다!
53777A

@ JDillon522 빠른 업데이트를 마쳤습니다. 이번에는 더 명확 해지기를 바랍니다.
53777A

@ JDillon522 샘플 스 니펫에 대해 조금 더 ...
53777A

좋은 싱글 톤 예제입니다. 그래서 나는 this어리석은 프로토 타입 예제에서 사용 했다. 왜냐하면 this메소드를 포함한 자체 속성을 참조하기 때문이다 . 코드에 대해 읽는 것이 가장 좋지 않지만 코드를 보면 더 많은 것을 배울 수 있습니다. ( MDN 비트 , Object Playground (amazing) 및 기타 몇 가지). " this우선 순위 "에 대해 의미하는 바를 설명 할 수 prototype있습니까? 더 자세히 살펴보고 싶습니다.
JDillon522
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.