425

私は最近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

どちらの場合も同じ動作が見られることに注意してください。これら2つのシナリオの主な違いは次のとおりです。

  • で使用されるオブジェクトはObject.create()実際には新しいオブジェクトのプロトタイプを形成しますがnew Function()、宣言されたプロパティ/関数からはプロトタイプを形成しません。
  • Object.create()機能構文の場合とは異なり、構文を使用してクロージャを作成することはできません。これは、JavaScriptの字句(vsブロック)タイプのスコープを考えると論理的です。

上記の記述は正しいですか?そして、私は何かが欠けていますか?いつ使用しますか?

編集:上記のコードサンプルのjsfiddleバージョンへのリンク:http://jsfiddle.net/rZfYL/

4

11 に答える 11

485

非常に簡単に言えば、new X関数Object.create(X.prototype)を追加で実行するconstructorことです。(そして、代わりに式の結果であるはずの実際のオブジェクトconstructorにチャンスを与えます。)returnthis

それでおしまい。:)

どうやら他の誰も新しいの定義を読んでいないので、残りの答えは混乱しているだけです。;)

于 2013-07-30T16:12:52.897 に答える
255

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.create私が話しているのは、Crockfordのシムではなく、ECMAScript5thEditionメソッドであることに注意してください。

このメソッドは最新のブラウザでネイティブに実装され始めています。この互換性テーブルを確認してください。

于 2010-11-12T16:22:29.893 に答える
218

両方の呼び出しで内部的に発生する手順は次のとおりです
(ヒント:唯一の違いは手順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にコンストラクターは実行されません。

于 2013-01-29T23:23:33.457 に答える
63

説明してみましょう(ブログでもっと):

  1. Carコンストラクターを作成するvar Car = function(){}と、内部的 には次のようになります。アクセスできない非表示のリンクjavascriptオブジェクトを作成するときのプロトタイプチェーンの図 が1つと、アクセス可能で実際のリンクが1つあります。Function.prototypeとCar.prototypeの両方に、への隠しリンクがあります。{prototype}Function.prototypeprototypeCar.prototypeconstructorCarObject.prototype
  2. new演算子とcreateメソッドを使用して2つの同等のオブジェクトを作成する場合は、次のようにする必要が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}に渡すことができます。nullMaruti = Object.create(null)

結論—メソッドを使用することにより、オブジェクトプロパティObject.createを自由に選択できます。{prototype}ではnew Car();、その自由はありません。

オブジェクト指向JavaScriptでの推奨される方法:

2つのオブジェクトaと。があるとしbます。

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

ここで、アクセスしたいaメソッドがあるとします。bそのためには、オブジェクトの継承が必要です(これらのメソッドにアクセスする場合にのみa、のプロトタイプにする必要があります)。bのプロトタイプをチェックするab、それらがプロトタイプを共有していることがわかります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()、継承に非常に役立ちます。

于 2014-09-03T03:45:22.913 に答える
48

これ:

var foo = new Foo();

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

非常に似ています。重要な違いの1つは、new Fooコンストラクターコードを実際に実行するのに対し、次Object.createのようなコードは実行しないことです。

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

Object.create()の2パラメータバージョンを使用すると、はるかに強力なことができることに注意してください。

于 2014-04-21T19:27:59.893 に答える
23

違いは、いわゆる「疑似古典的継承とプロトタイプ的継承」です。提案は、2つを混合するのではなく、コードで1つのタイプのみを使用することです。

疑似古典的継承(「new」演算子を使用)では、最初に疑似クラスを定義し、次にそのクラスからオブジェクトを作成するとします。たとえば、疑似クラス「Person」を定義してから、「Person」から「Alice」と「Bob」を作成します。

プロトタイプ継承(Object.createを使用)では、特定の人物「Alice」を直接作成し、次に「Alice」をプロトタイプとして使用して別の人物「Bob」を作成します。ここには「クラス」はありません。すべてがオブジェクトです。

内部的には、JavaScriptは「プロトタイプの継承」を使用します。「疑似古典的」な方法はほんの一部の砂糖です。

2つの方法の比較については、このリンクを参照してください。

于 2013-06-22T00:28:32.360 に答える
21
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キーワードを使用する場合、注意すべき点が2つあります。

a)関数はコンストラクターとして使用されます

b)function.prototypeオブジェクトがプロパティに渡される__proto__...または__proto__サポートされていない場合は、新しいオブジェクトがプロパティを検索する2番目の場所です。

2)Object.create(obj.prototype)オブジェクト(obj.prototype)を作成し、目的のオブジェクトに渡します。ただし、新しいオブジェクト__proto__もobj.prototypeを指しているという違いがあります(そのためにはxj9で参照してください)。

于 2013-12-21T00:18:11.673 に答える
21

オブジェクト作成バリアント。


バリアント1:' new Object() '->引数のないオブジェクトコンストラクタ。

var p1 = new Object(); // 'new Object()' create and return empty object -> {}

var p2 = new Object(); // 'new Object()' create and return empty object -> {}

console.log(p1); // empty object -> {}

console.log(p2); // empty object -> {}

// p1 and p2 are pointers to different objects
console.log(p1 === p2); // false

console.log(p1.prototype); // undefined

// empty object which is in fact Object.prototype
console.log(p1.__proto__); // {}

// empty object to which p1.__proto__ points
console.log(Object.prototype); // {}

console.log(p1.__proto__ === Object.prototype); // true

// null, which is in fact Object.prototype.__proto__
console.log(p1.__proto__.__proto__); // null

console.log(Object.prototype.__proto__); // null

ここに画像の説明を入力してください


バリアント2:' new Object(person) '->引数付きのオブジェクトコンストラクター。

const person = {
    name: 'no name',
    lastName: 'no lastName',
    age: -1
}

// 'new Object(person)' return 'person', which is pointer to the object ->
//  -> { name: 'no name', lastName: 'no lastName', age: -1 }
var p1 = new Object(person);

// 'new Object(person)' return 'person', which is pointer to the object ->
//  -> { name: 'no name', lastName: 'no lastName', age: -1 }
var p2 = new Object(person);

// person, p1 and p2 are pointers to the same object
console.log(p1 === p2); // true
console.log(p1 === person); // true
console.log(p2 === person); // true

p1.name = 'John'; // change 'name' by 'p1'
p2.lastName = 'Doe'; // change 'lastName' by 'p2'
person.age = 25; // change 'age' by 'person'

// when print 'p1', 'p2' and 'person', it's the same result,
// because the object they points is the same
console.log(p1); // { name: 'John', lastName: 'Doe', age: 25 }
console.log(p2); // { name: 'John', lastName: 'Doe', age: 25 }
console.log(person); // { name: 'John', lastName: 'Doe', age: 25 }

ここに画像の説明を入力してください


バリアント3.1:' Object.create(person) '。単純なオブジェクト「person」でObject.createを使用します。'Object.create(person)'は、新しい空のオブジェクトを作成(および返し)、同じ新しい空のオブジェクトにプロパティ'__proto__'を追加します。このプロパティ'__proto__'は、オブジェクト'person'を指します。

const person = {
        name: 'no name',
        lastName: 'no lastName',
        age: -1,
        getInfo: function getName() {
           return `${this.name} ${this.lastName}, ${this.age}!`;
    }
}

var p1 = Object.create(person);

var p2 = Object.create(person);

// 'p1.__proto__' and 'p2.__proto__' points to
// the same object -> 'person'
// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(p1.__proto__);
console.log(p2.__proto__);
console.log(p1.__proto__ === p2.__proto__); // true

console.log(person.__proto__); // {}(which is the Object.prototype)

// 'person', 'p1' and 'p2' are different
console.log(p1 === person); // false
console.log(p1 === p2); // false
console.log(p2 === person); // false

// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(person);

console.log(p1); // empty object - {}

console.log(p2); // empty object - {}

// add properties to object 'p1'
// (properties with the same names like in object 'person')
p1.name = 'John';
p1.lastName = 'Doe';
p1.age = 25;

// add properties to object 'p2'
// (properties with the same names like in object 'person')
p2.name = 'Tom';
p2.lastName = 'Harrison';
p2.age = 38;

// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(person);

// { name: 'John', lastName: 'Doe', age: 25 }
console.log(p1);

// { name: 'Tom', lastName: 'Harrison', age: 38 }
console.log(p2);

// use by '__proto__'(link from 'p1' to 'person'),
// person's function 'getInfo'
console.log(p1.getInfo()); // John Doe, 25!

// use by '__proto__'(link from 'p2' to 'person'),
// person's function 'getInfo'
console.log(p2.getInfo()); // Tom Harrison, 38!

ここに画像の説明を入力してください


バリアント3.2:' Object.create(Object.prototype) '。組み込みオブジェクト->'Object.prototype'でObject.createを使用します。'Object.create(Object.prototype)'は、新しい空のオブジェクトを作成(および返し)、同じ新しい空のオブジェクトにプロパティ'__proto__'を追加します。このプロパティ'__proto__'は、オブジェクト'Object.prototype'を指します。

// 'Object.create(Object.prototype)' :
// 1. create and return empty object -> {}.
// 2. add to 'p1' property '__proto__', which is link to 'Object.prototype'
var p1 = Object.create(Object.prototype);

// 'Object.create(Object.prototype)' :
// 1. create and return empty object -> {}.
// 2. add to 'p2' property '__proto__', which is link to 'Object.prototype'
var p2 = Object.create(Object.prototype);

console.log(p1); // {}

console.log(p2); // {}

console.log(p1 === p2); // false

console.log(p1.prototype); // undefined

console.log(p2.prototype); // undefined

console.log(p1.__proto__ === Object.prototype); // true

console.log(p2.__proto__ === Object.prototype); // true

ここに画像の説明を入力してください


バリアント4:' new SomeFunction() '

// 'this' in constructor-function 'Person'
// represents a new instace,
// that will be created by 'new Person(...)'
// and returned implicitly
function Person(name, lastName, age) {

    this.name = name;
    this.lastName = lastName;
    this.age = age;

    //-----------------------------------------------------------------
    // !--- only for demonstration ---
    // if add function 'getInfo' into
    // constructor-function 'Person',
    // then all instances will have a copy of the function 'getInfo'!
    //
    // this.getInfo: function getInfo() {
    //  return this.name + " " + this.lastName + ", " + this.age + "!";
    // }
    //-----------------------------------------------------------------
}

// 'Person.prototype' is an empty object
// (before add function 'getInfo')
console.log(Person.prototype); // Person {}

// With 'getInfo' added to 'Person.prototype',
// instances by their properties '__proto__',
// will have access to the function 'getInfo'.
// With this approach, instances not need
// a copy of the function 'getInfo' for every instance.
Person.prototype.getInfo = function getInfo() {
    return this.name + " " + this.lastName + ", " + this.age + "!";
}

// after function 'getInfo' is added to 'Person.prototype'
console.log(Person.prototype); // Person { getInfo: [Function: getInfo] }

// create instance 'p1'
var p1 = new Person('John', 'Doe', 25);

// create instance 'p2'
var p2 = new Person('Tom', 'Harrison', 38);

// Person { name: 'John', lastName: 'Doe', age: 25 }
console.log(p1);

// Person { name: 'Tom', lastName: 'Harrison', age: 38 }
console.log(p2);

// 'p1.__proto__' points to 'Person.prototype'
console.log(p1.__proto__); // Person { getInfo: [Function: getInfo] }

// 'p2.__proto__' points to 'Person.prototype'
console.log(p2.__proto__); // Person { getInfo: [Function: getInfo] }

console.log(p1.__proto__ === p2.__proto__); // true

// 'p1' and 'p2' points to different objects(instaces of 'Person')
console.log(p1 === p2); // false

// 'p1' by its property '__proto__' reaches 'Person.prototype.getInfo' 
// and use 'getInfo' with 'p1'-instance's data
console.log(p1.getInfo()); // John Doe, 25!

// 'p2' by its property '__proto__' reaches 'Person.prototype.getInfo' 
// and use 'getInfo' with 'p2'-instance's data
console.log(p2.getInfo()); // Tom Harrison, 38!

ここに画像の説明を入力してください

于 2018-03-22T17:29:25.390 に答える
12

内部的Object.createにこれを行います:

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

この構文は、JavaScriptがClassicalInheritanceを使用しているという幻想を取り除くだけです。

于 2010-11-12T16:19:13.173 に答える
12

この答えこのビデオ newキーワードに応じて、次のことを行います。

  1. 新しいオブジェクトを作成します。

  2. 新しいオブジェクトをコンストラクター関数(prototype)にリンクします。

  3. 変数thisが新しいオブジェクトを指すようにします。

  4. 新しいオブジェクトと暗黙のperformを使用してコンストラクター関数を実行しますreturn this

  5. コンストラクター関数名を新しいオブジェクトのプロパティに割り当てますconstructor

Object.create1stとステップのみを実行し2ndます!!!

于 2017-07-27T19:55:01.580 に答える
0

Object.create(Constructor.prototype)の一部ですnew Constructor

これはnew Constructor実装です

// 1. define constructor function

      function myConstructor(name, age) {
        this.name = name;
        this.age = age;
      }
      myConstructor.prototype.greet = function(){
        console.log(this.name, this.age)
      };

// 2. new operator implementation

      let newOperatorWithConstructor = function(name, age) {
        const newInstance = new Object(); // empty object
        Object.setPrototypeOf(newInstance, myConstructor.prototype); // set prototype

        const bindedConstructor = myConstructor.bind(newInstance); // this binding
        bindedConstructor(name, age); // execute binded constructor function

        return newInstance; // return instance
      };

// 3. produce new instance

      const instance = new myConstructor("jun", 28);
      const instance2 = newOperatorWithConstructor("jun", 28);
      console.log(instance);
      console.log(instance2);
      

new Constructor実装にはObject.createメソッドが含まれています

      newOperatorWithConstructor = function(name, age) {
        const newInstance = Object.create(myConstructor.prototype); // empty object, prototype chaining

        const bindedConstructor = myConstructor.bind(newInstance); // this binding
        bindedConstructor(name, age); // execute binded constructor function

        return newInstance; // return instance
      };

      console.log(newOperatorWithConstructor("jun", 28));
于 2020-09-27T18:26:14.900 に答える