자바 스크립트 상속 : Object.create vs new


123

JavaScript에서이 두 예제의 차이점은 무엇입니까?

전제 조건 :

function SomeBaseClass(){
}

SomeBaseClass.prototype = {
    doThis : function(){
    },

    doThat : function(){
    }
}

Object.create를 사용한 상속 예제 A :

function MyClass(){
}

MyClass.prototype = Object.create(SomeBaseClass.prototype);

새 키워드를 사용한 상속 예 B

function MyClass(){
}

MyClass.prototype = new SomeBaseClass();

두 예제 모두 같은 일을하는 것 같습니다. 언제 다른 것을 선택하겠습니까?

추가 질문 : 함수 자체 생성자에 대한 참조가 프로토 타입에 저장되는 아래 링크 (15 행)의 코드를 고려하십시오. 이것이 왜 유용합니까?

https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js

발췌 (링크를 열지 않으려는 경우) :

THREE.ImageLoader.prototype = {

    constructor: THREE.ImageLoader
}

23
도대체 이것이 중복으로 표시되는 이유!?! 다른 질문과 답변은를 언급하지 마십시오 Object.create. 이것은 실수이므로 다시 열어야합니다.
Scott Rippey 2014 년

2
어떤 경우의 중복입니다 stackoverflow.com/questions/4166616/...은
스콧 Rippey

1
그 댓글에 13 표가 있지만 아직 다시 열리지 않았습니다 ..?!
TJ

답변:


111

귀하의 질문에서 귀하는 Both examples seem to do the same thing, 전혀 사실이 아닙니다.

첫 번째 예

function SomeBaseClass(){...}
SomeBaseClass.prototype = {
    doThis : function(){...},
    doThat : function(){...}
}
function MyClass(){...}
MyClass.prototype = Object.create(SomeBaseClass.prototype);

이 예에서, 당신은 단지 상속하고 SomeBaseClass' prototype있지만 SomeBaseClass같은 속성이 있다면 어떨까요 ?

function SomeBaseClass(){ 
    this.publicProperty='SomeValue'; 
}

그리고 당신이 그것을 사용한다면

var obj=new MyClass();
console.log(obj.publicProperty); // undefined
console.log(obj);​

obj개체가 없습니다 publicProperty같은 속성을 이 예제 .

두 번째 예

MyClass.prototype = new SomeBaseClass();

constructor함수를 실행 SomeBaseClass하고 전체 SomeBaseClass개체 의 인스턴스를 만들고 상속 합니다. 그래서, 당신이 사용한다면

    var obj=new MyClass();
    console.log(obj.publicProperty); // SomeValue
    console.log(obj);​

이 경우 publicProperty속성은 이 예제obj 와 같이 객체 에서도 사용할 수 있습니다 .

(가)부터 Object.create오래된 브라우저에서 사용할 수 없습니다,이 경우 당신은 사용할 수 있습니다

if(!Object.create)
{
    Object.create=function(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
}

위의 코드는 Object.create사용할 수없는 경우에만 함수를 추가 하므로 Object.create함수 를 사용할 수 있으며 위의 코드는 Object.create실제로 수행하는 작업을 설명한다고 생각합니다 . 어떤 식 으로든 도움이되기를 바랍니다.


6
안녕하세요 셰이크. 노력해 주셔서 감사합니다. 예, 차이점은 생성자가 두 번째 예제에서는 실행되지만 첫 번째 예제에서는 실행되지 않는다는 것입니다. (제 경우에는 바람직합니다). super 구현에서 상속되지 않는 정의되지 않은 public 속성에 대해서는 자식 생성자에서 super를 호출하면됩니다. SomeBaseClass.call (this). 이 바이올린 확인 jsfiddle.net/NhQGB
ChrisRich

라이브러리 / 프레임 워크를 사용하지 않고 JS에서 적절한 상속을위한 매우 간단한 방법을 찾고 있습니다. 이 예제 (위의 바이올린)가 최신 브라우저에 가장 적합한 접근 방식이라고 생각합니다. 아마도 Object.Create 폴리 필이 레거시 브라우저에 대한 지원을 추가 할 수 있습니까?
ChrisRich

그래서 기본적으로 요약하면 .prototype = new를 수행하면 기본 클래스에서 할당 한 값을 상속하고 object.create를 수행 할 때 기본 클래스의 프로토 타입에있는 것만 상속하는 것입니다.
davidjnelson

이 "MyClass.prototype = new SomeBaseClass ()"는 MyClass의 인스턴스가 아직 생성되지 않은 경우 SomeBaseClass의 새 인스턴스가 생성된다는 의미입니까?

아니요, 기본 개체를 만들 때만 프로토 타입이로 설정됩니다 SomeBaseClass.
The Alpha

39

두 예제 모두 동일한 작업을 수행하는 것 같습니다.

그것은 당신의 경우에 사실입니다.

언제 다른 하나를 선택하겠습니까?

SomeBaseClass함수 본문이이은으로 실행 얻을 것이다 new키워드. 이것은 일반적으로 의도 된 것이 아닙니다. 프로토 타입 체인 만 설정하려고합니다. 어떤 경우에는 개인 범위 변수가 동일한 권한있는 메서드를 상속하므로 모든 인스턴스에서 공유되는 개체 를 실제로 인스턴스화 하기 때문에 심각한 문제가 발생할 수도 있습니다 MyClass. 다른 부작용은 상상할 수 있습니다.

따라서 일반적으로 Object.create. 그러나 일부 레거시 브라우저에서는 지원되지 않습니다. new이것이 종종 (분명한) 해를 끼치 지 않기 때문에-접근을 너무 자주 보는 이유 입니다. 또한 이 답변을 살펴보십시오 .


이것은 가장 좋은 대답이다, 잘 설명
SPEX

8

Object.create()의도 한대로 사용하면 차이가 분명해집니다 . 사실, 그것은 prototype당신의 코드 에서 단어를 완전히 숨기고, 내부 에서 일을 할 것입니다. 를 사용하면 Object.create()다음과 같이 갈 수 있습니다.

var base =  {
    doThis : function(){
    },

    doThat : function(){
    }
};

그런 다음 여기에서 다른 객체를 확장 / 상속 할 수 있습니다.

var myObject = Object.create( base );
// myObject will now link to "base" via the prototype chain internally

그래서 이것은 또 다른 개념, 더 "객체 지향적 인"상속 방식입니다. Object.create()예를 들어 사용하는 "생성자 기능"은 없습니다 . 그러나 물론 이러한 객체 내에서 자체 정의 생성자 함수를 만들고 호출 할 수 있습니다.

사용 Object.create()에 대한 한 가지 주장은 Javascripts default way를 사용하는 것보다 다른 객체에서 / * inherit * 를 혼합 하는 것이 더 자연스럽게 보일 수 있다는 것 입니다.


7
Object.createnew생성자 함수가 필요할 때 고전적인 접근 방식을 실제로 대체 할 수 없습니다
Bergi

1
확실히 @Bergi가 가능합니다. 이 블로그 게시물을보십시오 : davidwalsh.name/javascript-objects-deconstruction . 초기화 객체를 Object.create ()에 두 번째 매개 변수로 전달할 수도 있습니다.
LocalPCGuy 2015

@LocalPCGuy : 아니요 Object.create. 클로저를 만드는 데 필요한 함수를 호출하지 않기 때문 입니다. 물론, 함께 Object.create당신 넣을 수 있습니다 init그 즉시 개체 및 통화 방법을 그리고 어쩌면 반환 this그래서 당신은 간결한 구문을 얻을 -하지만 대기, 다음 생성자를.
Bergi

1
init 함수 호출은 생성자와 유사하게 작동하지만 생성자는 아닙니다. 그리고 그 방법을 사용하면 고전적인 접근 방식을 Object.create로 정확하게 바꿀 수 있습니다. 그리고 객체 연결의 멘탈 모델은 'new'를 통해 생성 된 모델보다 훨씬 간단합니다.
LocalPCGuy 2015

글쎄요, 저의 멘탈 모델 new은 "객체 연결" 을 사용하므로 큰 차이는 없습니다. 실제로 .constructor라는 두 가지가 있습니다. 이 .init함수에는 .prototype프로토 타입 객체를 다시 가리키는 속성 이 없습니다 . 나머지는 구문입니다 - 내가 선호하는 new X이상 Object.create(x).init().
Bergi

0

저는 자바 스크립트의 전문가는 아니지만 "Object.create"와 "new"의 차이점을 이해하는 간단한 예제입니다.

1 단계 : 몇 가지 속성 및 작업을 사용하여 부모 함수를 만듭니다.

function Person() {

this.name = 'venkat';

this.address = 'dallas';

this.mobile='xxxxxxxxxx'

}

Person.prototype.func1 = function () {

    return this.name + this.address;
}

2 단계 : New 키워드를 사용하여 Person 함수 위에 확장되는 자식 함수 (PersonSalary)를 만듭니다 .

function PersonSalary() {
    Person.call(this);
}
PersonSalary.prototype = new Person();

PersonSalary();

3 단계 : Object.create 키워드를 사용하여 Person 함수 위에 확장되는 두 번째 자식 함수 (PersonLeaves)를 만듭니다 .

function PersonLeaves() {
 Person.call(this);
}
PersonLeaves.prototype = Object.create(Person.prototype);


PersonLeaves();

// 이제 두 하위 함수 프로토 타입을 모두 확인합니다.

PersonSalary.prototype
PersonLeaves.prototype

이 두 자식 함수는 모두 Person (parent function) 프로토 타입에 연결되고 메서드에 액세스 할 수 있지만 new를 사용하여 자식 함수를 생성하면 필요하지 않은 모든 부모 속성이 포함 된 새로운 객체가 반환됩니다. 우리가 원하지 않는 부모 함수가 실행되는 "New"를 사용하는 객체 또는 함수.

요점은 다음과 같습니다.

부모 함수의 일부 메서드에 위임하고 새 객체를 생성하지 않으려면 Object.create를 사용하는 것이 가장 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.