[javascript] Object.create ()와 new SomeFunction ()의 차이점 이해

나는 최근 Object.create()에 JavaScript 에서 메소드를 우연히 발견했으며을 사용하여 객체의 새 인스턴스를 만드는 것과 다른 점과 다른 것을 사용하려고 할 때를 추론하려고합니다 new SomeFunction().

다음 예제를 고려하십시오.

var test = {
  val: 1,
  func: function() {
    return this.val;
  }
};
var testA = Object.create(test);

testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2

console.log('other test');
var otherTest = function() {
  this.val = 1;
  this.func = function() {
    return this.val;
  };
};

var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1 
console.log(otherTestB.val); // 2

console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2

두 경우 모두 동일한 동작이 관찰됩니다. 이 두 시나리오의 주요 차이점은 다음과 같습니다.

  • Object.create()실제로 사용 된 객체 는 새로운 객체의 프로토 타입을 형성하는 반면 new Function(), 선언 된 속성 / 함수는 프로토 타입을 형성하지 않습니다.
  • Object.create()기능적 구문 과 마찬가지로 구문을 사용하여 클로저를 작성할 수 없습니다 . JavaScript의 어휘 (vs 블록) 유형 범위가 주어지면 논리적입니다.

위의 진술이 맞습니까? 그리고 뭔가 빠졌습니까? 언제 다른 것을 사용 하시겠습니까?

편집 : 위 코드 샘플의 jsfiddle 버전 링크 : http://jsfiddle.net/rZfYL/



답변

Object.create에 사용 된 객체는 실제로 새 객체의 프로토 타입을 형성하며, new Function () 양식에서와 같이 선언 된 속성 / 함수는 프로토 타입을 형성하지 않습니다.

예, Object.create첫 번째 인수로 전달 된 객체에서 직접 상속되는 객체를 만듭니다.

생성자 함수를 사용하면 새로 생성 된 객체가 생성자의 프로토 타입에서 상속됩니다. 예 :

var o = new SomeConstructor();

위의 예에서는에서 o직접 상속합니다 SomeConstructor.prototype.

여기에는 차이점이 있습니다. 반면 새로 생성 된 객체가에서 상속 받도록 설정 하면 Object.create어떤 것도 상속하지 않는 객체를 만들 수 있습니다 .Object.create(null);SomeConstructor.prototype = null;Object.prototype

기능적 구문에서와 마찬가지로 Object.create 구문으로 클로저를 작성할 수 없습니다. JavaScript의 어휘 (vs 블록) 유형 범위가 주어지면 논리적입니다.

예를 들어 속성 ​​설명자 인수를 사용하여 클로저를 만들 수 있습니다.

var o = Object.create({inherited: 1}, {
  foo: {
    get: (function () { // a closure
      var closured = 'foo';
      return function () {
        return closured+'bar';
      };
    })()
  }
});

o.foo; // "foobar"

저는 Object.createCrockford의 심이 아니라 ECMAScript 5th Edition 방법 에 대해 이야기하고 있습니다.

이 방법은 최신 브라우저에서 기본적으로 구현되기 시작 합니다 . 이 호환성 표를 확인하십시오 .


답변

아주 간단했다 new X입니다 Object.create(X.prototype)추가로 실행하는 constructor기능. (그리고 대신 실제 표현식의 결과가되어야하는 실제 객체에 constructor기회를 return줍니다 this.)

그게 다야. 🙂

나머지는 그 new어느 것도 그 정의를 읽지 않기 때문에 나머지 대답은 혼란 스럽습니다 . 😉


답변

다음은 두 호출 모두에 대해 내부적으로 수행되는 단계입니다.
(힌트 : 유일한 차이점은 3 단계입니다)


new Test():

  1. new Object()obj 생성
  2. 설정 obj.__proto__Test.prototype
  3. return Test.call(obj) || obj;
    // normally obj is returned but constructors in JS can return a value

Object.create( Test.prototype )

  1. new Object()obj 생성
  2. 설정 obj.__proto__Test.prototype
  3. return obj;

따라서 기본적으로 Object.create생성자를 실행하지 않습니다.


답변

설명해 드리겠습니다 ( 블로그 에 대한 자세한 내용 참조 ).

  1. Car생성자 를 작성할 때 var Car = function(){}, 이것은 내부적으로 방법입니다 :
    자바 스크립트 객체를 만들 때 프로토 체인의 다이어그램
    우리는 접근 할 수없는 하나의 {prototype}숨겨진 링크 Function.prototype와 접근 할 수 있고 실제 의 prototype링크를 Car.prototype가지고 있습니다 . Function.prototype과 Car.prototype 모두에 대한 숨겨진 링크가 있습니다.constructorCarObject.prototype
  2. 우리가 사용하여 동일한 두 개체를 생성 할 때 new연산자와 create방법을 우리는 이런 식으로 할 필요가 : Honda = new Car();Maruti = Object.create(Car.prototype). 다른 객체 생성 방법을위한 프로토 타입 체인 다이어그램
    무슨 일이야?

    Honda = new Car();— 이와 같은 객체를 만들면 숨겨진 {prototype}속성이 가리 킵니다 Car.prototype. 따라서 여기서 {prototype}Honda 객체는 항상 있습니다 . 객체 Car.prototype{prototype}속성 을 변경할 수있는 옵션이 없습니다 . 새로 만든 객체의 프로토 타입을 변경하려면 어떻게합니까?
    Maruti = Object.create(Car.prototype)— 이와 같은 객체를 만들 때 객체의 {prototype}속성 을 선택할 수있는 추가 옵션이 있습니다 . Car.prototype을 원하는 경우 {prototype}함수의 매개 변수로 전달하십시오. {prototype}객체를 원하지 않으면 다음 null과 같이 전달할 수 있습니다 Maruti = Object.create(null).

결론 —이 방법 Object.create을 사용하면 객체 {prototype}속성을 자유롭게 선택할 수 있습니다. 의 new Car();자유는 없습니다.

OO JavaScript에서 선호되는 방법 :

두 개의 객체 a와 가 있다고 가정합니다 b.

var a = new Object();
var b = new Object();

이제 접근하려는 a메소드가 있다고 가정 해 봅시다 b. 이를 위해서는 객체 상속이 필요합니다 ( 해당 메소드에 액세스하려는 경우에만 a프로토 타입이어야 함 b). 우리의 프로토 타입을 선택하면 a그리고 b우리는 그들이 프로토 타입을 공유하는 것을 발견 할 것이다 Object.prototype.

Object.prototype.isPrototypeOf(b); //true
a.isPrototypeOf(b); //false (the problem comes into the picture here).

문제 — 객체 a를 프로토 타입으로 원 b하지만 여기서는 프로토 타입을 b사용하여 객체 를 만들었습니다 Object.prototype.
솔루션 — ECMAScript 5가 도입 Object.create()되어 그러한 상속을 쉽게 달성 할 수 있습니다. 다음 b과 같이 객체를 생성 하면 :

var b = Object.create(a);

그때,

a.isPrototypeOf(b);// true (problem solved, you included object a in the prototype chain of object b.)

따라서 객체 지향 스크립팅을 수행하는 경우 Object.create()상속에 매우 유용합니다.


답변

이:

var foo = new Foo();

var foo = Object.create(Foo.prototype);

꽤 비슷합니다. 한 가지 중요한 차이점은 new Foo실제로 생성자 코드를 실행하지만 Object.create다음과 같은 코드는 실행하지 않는다는 것입니다.

function Foo() {
    alert("This constructor does not run with Object.create");
}

2- 매개 변수 버전을 사용하면 Object.create()훨씬 더 강력한 작업을 수행 할 수 있습니다.


답변

차이점은 이른바 “가상 고전 대 프로토 타입 상속”입니다. 코드에서 한 가지 유형 만 사용하고 두 유형을 혼합하지 말 것을 제안합니다.

의사 클래식 상속 ( “new”연산자 사용)에서 먼저 의사 클래스를 정의한 다음 해당 클래스에서 오브젝트를 작성한다고 가정하십시오. 예를 들어, 의사 클래스 “Person”을 정의한 다음 “Person”에서 “Alice”및 “Bob”을 작성하십시오.

프로토 타입 상속 (Object.create 사용)에서는 특정 사람 “Alice”를 직접 만든 다음 “Alice”를 프로토 타입으로 사용하여 다른 사람 “Bob”을 만듭니다. 여기에는 “클래스”가 없습니다. 모두 개체입니다.

내부적으로 JavaScript는 “프로토 타입 상속”을 사용합니다. “의사 고전적인”방법은 설탕 일뿐입니다.

두 가지 방법을 비교하려면 이 링크 를 참조하십시오 .


답변

function Test(){
    this.prop1 = 'prop1';
    this.prop2 = 'prop2';
    this.func1 = function(){
        return this.prop1 + this.prop2;
    }
};

Test.prototype.protoProp1 = 'protoProp1';
Test.prototype.protoProp2 = 'protoProp2';
var newKeywordTest = new Test();
var objectCreateTest = Object.create(Test.prototype);

/* Object.create   */
console.log(objectCreateTest.prop1); // undefined
console.log(objectCreateTest.protoProp1); // protoProp1 
console.log(objectCreateTest.__proto__.protoProp1); // protoProp1

/* new    */
console.log(newKeywordTest.prop1); // prop1
console.log(newKeywordTest.__proto__.protoProp1); // protoProp1

요약:

1) new 키워드에는 두 가지 유의할 사항이 있습니다.

a) 함수는 생성자로 사용됩니다

b) function.prototype객체가 __proto__속성에 전달 되거나 …__proto__ 지원되지 않는 경우 새 객체가 속성을 찾는 두 번째 장소입니다

2) Object.create(obj.prototype)당신 과 함께 객체 ( obj.prototype)를 만들고 그것을 의도 한 객체로 전달하고 있습니다 .. 이제 새로운 객체 __proto__가 obj.prototype을 가리키고 있다는 차이점이 있습니다 (xj9로 ans를 참조하십시오)