JavaScriptでオブジェクトを作成するにはどの方法が最適ですか?オブジェクトのプロパティの前に「var」が必要ですか?


177

これまで、JavaScriptでオブジェクトを作成する3つの方法を見てきました。オブジェクトの作成に最適な方法とその理由を教えてください。

また、これらのすべての例で、varプロパティの前にキーワードが使用されていないこともわかりました。なぜですか?varプロパティは変数であると述べたように、プロパティの名前の前に宣言する必要はありませんか?

2番目と3番目の方法では、オブジェクトの名前は大文字ですが、1番目の方法では、オブジェクトの名前は小文字です。オブジェクト名にはどのケースを使用すればよいですか?

最初の方法:

function person(fname, lname, age, eyecolor){
  this.firstname = fname;
  this.lastname = lname;
  this.age = age;
  this.eyecolor = eyecolor;
}

myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");

2番目の方法:

var Robot = {
  metal: "Titanium",
  killAllHumans: function(){
    alert("Exterminate!");
  }
};

Robot.killAllHumans();

3番目の方法—配列構文を使用するJavaScriptオブジェクト:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }

2
「var」は変数のスコープに応じて使用され、グローバルかどうかを定義し、検索すると違いがわかります。
jackJoe

80
殺人ロボットを作成する場合は、常にを使用varしてください。省略した場合、グローバルになります
mykhal

9
「varは変数のスコープに応じて使用されます」 -これは悪い習慣です-どのスコープにいても使用する必要があります
treecoder

1
メソッドについてはどうObject.create()ですか?
最大

「プロパティは変数であると述べたように」が明確になっているとよいでしょう。どなた"?それはどこに言及されていますか?特定の引用を引用できますか?
user4642212 2018

回答:


181

最善の方法はありません。それは、ユースケースによって異なります。

  • 複数の同様のオブジェクトを作成する場合は、方法1を使用します。あなたの例では、Person(名前は大文字で始める必要があります)はコンストラクタ関数と呼ばれます。これは他のオブジェクト指向言語のクラスに似ています
  • 種類が1つのオブジェクト(シングルトンなど)だけが必要な場合は、方法2を使用します。このオブジェクトを別のオブジェクトから継承したい場合は、コンストラクタ関数を使用する必要があります。
  • オブジェクトの他のプロパティに応じてオブジェクトのプロパティを初期化する場合、または動的なプロパティ名がある場合は、方法3を使用します。

更新: 3番目の方法の要求された例として。

依存プロパティ:

以下はを参照しないと機能しthisませbook。オブジェクトリテラル内の他のプロパティの値でプロパティを初期化する方法はありません。

var book = {
    price: somePrice * discount,
    pages: 500,
    pricePerPage: this.price / this.pages
};

代わりに、次のことができます。

var book = {
    price: somePrice * discount,
    pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;

動的プロパティ名:

プロパティ名が変数に格納されているか、式によって作成されている場合は、ブラケット表記を使用する必要があります。

var name = 'propertyName';

// the property will be `name`, not `propertyName`
var obj = {
    name: 42
}; 

// same here
obj.name = 42;

// this works, it will set `propertyName`
obj[name] = 42;

1
あなたの答えに感謝...これで、最初のポイントを理解しました。このようなものを望む場合は、way1を使用できますmyFather = new person( "John"、 "Doe"、50、 "blue"); myMother = new person( "gazy"、 "Doe"、45、 "brown"); myBrother = new person( "poll"、 "Doe"、15、 "blue");
ジャムナ

obj [name] = 42を意味すると思います。そうですか?
キースピンソン

オプション2と3は実質的に同じですが、オブジェクトを作成した後でプロパティを割り当てていることを指摘しておきます。オブジェクトリテラルを使用してオブジェクトを作成しているため、これはリテラル表記と呼ばれます。内部的には、これは実際には「new Object()」を呼び出します。詳しくは、developer.mozilla.org
en

2番目のケースでは、spread演算子を使用して...別のオブジェクトから継承することは意味がありますか?
6パックの子供、2018

114

関数を定義するにはさまざまな方法があります。それは完全にあなたの要件に基づいています。以下はいくつかのスタイルです:-

  1. オブジェクトコンストラクタ
  2. リテラルコンストラクター
  3. 関数ベース
  4. プロトタイプベース
  5. 機能とプロトタイプベース
  6. シングルトンベース

例:

  1. オブジェクトコンストラクタ
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. リテラルコンストラクター
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. 関数コンストラクタ
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. プロトタイプ
function Person(){};

Person.prototype.name = "Anand";
  1. 機能/プロトタイプの組み合わせ
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. シングルトン
var person = new function(){
  this.name = "Anand"
} 

混乱があれば、コンソールで試すことができます。


こんにちは@Alex_Nabu-私はすでに投稿で例を共有しています。それでも問題が解決しない場合は、私を更新してください。私がお手伝いします。
Anand Deep Singh 2015年

1
var person最終的にまったく同じインスタンスを生成するすべての例を作成するほうが理にかなっていますか?たとえば、関数コンストラクターで単純に追加できvar person = new Person("Anand")ます。一見ランダムなセミコロンの使い方はどうなっていますか?:P
cregox

2
それぞれの方法の長所と短所を説明する価値を追加します。
RayLoveless 2018

10

オブジェクトを作成する「最善の方法」はありません。どちらの方法にも、ユースケースに応じてメリットがあります。

コンストラクター・パターン(newそれを呼び出すためにオペレーターとペアになっている関数)は、プロトタイプ継承を使用する可能性を提供しますが、他の方法はそうではありません。したがって、プロトタイプの継承が必要な場合は、コンストラクター関数が適しています。

ただし、プロトタイプの継承が必要な場合Object.createは、継承をより明確にするを使用することもできます。

オブジェクトリテラル(例:)の作成は、var obj = {foo: "bar"};作成時に設定したいすべてのプロパティが手元にある場合に効果的です。

プロパティを後で設定NewObject.property1するNewObject['property1']場合、プロパティ名がわかっている場合よりも構文の方が一般的に推奨されます。しかし、後者は、事前にプロパティの名前を実際に持っていない場合に便利です(例:)NewObject[someStringVar]

お役に立てれば!


6

それはあなたが望むものに依存すると思います。単純なオブジェクトの場合は、2番目の方法を使用できると思います。オブジェクトが大きくなり、同様のオブジェクトを使用する予定がある場合は、最初の方法の方が良いと思います。そうすれば、プロトタイプを使用して拡張することもできます。

例:

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.getCircumference = function() {
    return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
    return Math.PI * this.radius * this.radius;
}

私は3番目の方法の大ファンではありませんが、動的にプロパティを編集する場合などに非常に役立ちvar foo='bar'; var bar = someObject[foo];ます。


3

JavaScriptでオブジェクトを作成するには多くの方法があります。コンストラクター関数を使用してオブジェクトまたはオブジェクトリテラル表記を作成するには、JavaScriptでalotを使用します。Objectのインスタンスを作成し、それにプロパティとメソッドを追加する場合も、JavaScriptでオブジェクトを作成する一般的な方法は3つあります。

コンストラクター関数

Date()、Number()、Boolean()など、私たち全員が時々使用できる組み込みのコンストラクター関数があり、すべてのコンストラクター関数は大文字で始まりますが、JavaScriptでカスタムコンストラクター関数を作成できますこのような:

function Box (Width, Height, fill) {  
  this.width = Width;  // The width of the box 
  this.height = Height;  // The height of the box 
  this.fill = true;  // Is it filled or not?
}  

そして、単にnew()を使用してそれを呼び出し、コンストラクターの新しいインスタンスを作成し、以下のようなものを作成し、パラメーターを入力してコンストラクター関数を呼び出すことができます。

var newBox = new Box(8, 12, true);  

オブジェクトリテラル

オブジェクトリテラルの使用は、JavaScriptでオブジェクトを作成する場合に非常によく使用されます。これは、単純なオブジェクトを作成する例です。オブジェクトのプロパティが定義されている限り、それらをオブジェクトのプロパティに割り当てることができます。

var person = { 
    name: "Alireza",
    surname: "Dezfoolian"
    nose: 1,  
    feet: 2,  
    hands: 2,
    cash: null
};  

プロトタイピング

オブジェクトを作成した後、さらに多くのメンバーのプロトタイプを作成できます。たとえば、ボックスに色を追加すると、次のようになります。

Box.prototype.colour = 'red';

2

ここで多くの人がオブジェクトの作成に最善の方法はないと言いますが、2019年のようにJavaScriptでオブジェクトを作成する方法が非常に多い理由には根拠があり、これはさまざまな反復でのJavaScriptの進行に関係していますEcmaScriptリリースの1997年までさかのぼります。

ECMAScript 5以前は、オブジェクトを作成する方法は2つしかありませんでした。コンストラクター関数またはリテラル表記(new Object()のより良い代替手段)です。コンストラクター関数表記を使用すると、(新しいキーワードを使用して)複数のインスタンスにインスタンス化できるオブジェクトを作成しますが、リテラル表記は、シングルトンのような単一のオブジェクトを提供します。

// constructor function
function Person() {};

// literal notation
var Person = {};

使用するメソッドに関係なく、JavaScriptオブジェクトはキーと値のペアの単なるプロパティです。

// Method 1: dot notation
obj.firstName = 'Bob';

// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';

// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
    value: 'Bob',
    writable: true,
    configurable: true,
    enumerable: false
})

// Method 4: Object.defineProperties
Object.defineProperties(obj, {
  firstName: {
    value: 'Bob',
    writable: true
  },
  lastName: {
    value: 'Smith',
    writable: false
  }
});

JavaScriptの初期バージョンでは、クラスベースの継承を模倣する唯一の実際の方法は、コンストラクター関数を使用することでした。コンストラクター関数は、「new」キーワードで呼び出される特別な関数です。慣例により、関数識別子は大文字で表記されますが、必須ではありません。コンストラクターの内部では、 'this'キーワードを参照して、コンストラクター関数が暗黙的に作成しているオブジェクトにプロパティを追加します。明示的にreturnキーワードを使用して何かを返さない限り、コンストラクター関数は、プロパティが設定された新しいオブジェクトを暗黙的に呼び出し元の関数に返します。

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.sayName = function(){
        return "My name is " + this.firstName + " " + this.lastName;
    }
} 

var bob = new Person("Bob", "Smith");
bob instanceOf Person // true

sayNameメソッドに問題があります。通常、オブジェクト指向クラスベースのプログラミング言語では、クラスをファクトリとして使用してオブジェクトを作成します。各オブジェクトには独自のインスタンス変数がありますが、クラスブループリントで定義されているメソッドへのポインターがあります。残念ながら、JavaScriptのコンストラクター関数を使用すると、呼び出されるたびに、新しく作成されたオブジェクトに新しいsayNameプロパティが定義されます。したがって、各オブジェクトには独自のsayNameプロパティがあります。これは、より多くのメモリリソースを消費します。

メモリリソースの増加に加えて、コンストラクタ関数内でメソッドを定義すると、継承の可能性がなくなります。この場合も、メソッドは新しく作成されたオブジェクトのプロパティとして定義され、他のオブジェクトは定義されないため、継承は同様に機能しません。したがって、JavaScriptはプロトタイプチェーンを継承の形式として提供し、JavaScriptをプロトタイプ言語にします。

親がいて、親が子の多くのプロパティを共有している場合、子はそれらのプロパティを継承する必要があります。ES5以前は、次のようにして実現されていました。

function Parent(eyeColor, hairColor) {
    this.eyeColor = eyeColor;
    this.hairColor = hairColor;
}

Parent.prototype.getEyeColor = function() {
  console.log('has ' + this.eyeColor);
}

Parent.prototype.getHairColor = function() {
  console.log('has ' + this.hairColor);
}

function Child(firstName, lastName) {
  Parent.call(this, arguments[2], arguments[3]);
  this.firstName = firstName;
  this.lastName = lastName;
}

Child.prototype = Parent.prototype;

var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair

上記のプロトタイプチェーンの利用方法には、癖があります。プロトタイプはライブリンクであるため、プロトタイプチェーン内の1つのオブジェクトのプロパティを変更すると、別のオブジェクトの同じプロパティも変更されます。明らかに、子の継承されたメソッドを変更しても、親のメソッドは変更されません。Object.createは、ポリフィルを使用してこの問題を解決しました。したがって、Object.createを使用すると、プロトタイプチェーン内の親の同じプロパティに影響を与えることなく、プロトタイプチェーン内の子のプロパティを安全に変更できます。

ECMAScript 5ではObject.createが導入され、前述のオブジェクト作成のコンストラクター関数のバグが解決されました。Object.create()メソッドは、新しく作成されたオブジェクトのプロトタイプとして既存のオブジェクトを使用して、新しいオブジェクトを作成します。新しいオブジェクトが作成されるため、プロトタイプチェーンの子プロパティを変更すると、チェーン内のそのプロパティへの親の参照が変更されるという問題はなくなります。

var bobSmith = {
    firstName: "Bob",
    lastName: "Smith",
    sayName: function(){
      return "My name is " + this.firstName + " " + this.lastName;
    }
}

var janeSmith = Object.create(bobSmith, {
    firstName : {  value: "Jane" }
})

console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.

ES6より前は、関数コンストラクターとObject.createを利用するための一般的な作成パターンは次のとおりです。

const View = function(element){
  this.element = element;
}

View.prototype = {
  getElement: function(){
    this.element
  }
}

const SubView = function(element){
  View.call(this, element);
}

SubView.prototype = Object.create(View.prototype);

現在、コンストラクター関数と組み合わせたObject.createは、JavaScriptでのオブジェクトの作成と継承に広く使用されています。ただし、ES6はクラスの概念を導入しました。これは主に、JavaScriptの既存のプロトタイプベースの継承に対する構文上の砂糖です。クラス構文は、JavaScriptに新しいオブジェクト指向の継承モデルを導入しません。したがって、JavaScriptは原型言語のままです。

ES6クラスは継承をはるかに簡単にします。親クラスのプロトタイプ関数を手動でコピーして子クラスのコンストラクターをリセットする必要がなくなりました。

// create parent class
class Person {
  constructor (name) {
    this.name = name;
  }
}

// create child class and extend our parent class
class Boy extends Person {
  constructor (name, color) {
    // invoke our parent constructor function passing in any required parameters
    super(name);

    this.favoriteColor = color;
  }
}

const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue

全体として、JavaScriptでのオブジェクト作成のこれら5つの異なる戦略は、EcmaScript標準の進化と一致しました。


0

もちろん、最善の方法があります。JavaScriptのオブジェクトには、列挙可能なプロパティと列挙不可能なプロパティがあります。

var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]

上記の例では、空のオブジェクトに実際にプロパティがあることがわかります。

では、どちらが最善の方法であるかを見てみましょう。

var new_object = Object.create(null)

new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc

console.log("toString" in new_object) //=> false

上記の例では、ログはfalseを出力します。

次に、他のオブジェクト作成方法が正しくない理由を見てみましょう。

//Object constructor
var object = new Object();

console.log("toString" in object); //=> true

//Literal constructor
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 

console.log("toString" in person); //=> true

//function Constructor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
}

var person = new Person ('landi')

console.log("toString" in person); //=> true

//Prototype
function Person(){};

Person.prototype.name = "Anand";

console.log("toString" in person); //=> true

//Function/Prototype combination
function Person2(name){
  this.name = name;
} 

Person2.prototype.getName = function(){
  return this.name
}

var person2 = new Person2('Roland')

console.log("toString" in person2) //=> true

上記のように、すべての例はtrueを記録します。これはfor in、オブジェクトにプロパティがあるかどうかを確認するループがある場合は、おそらく間違った結果につながることを意味します。

最善の方法は簡単ではないことに注意してください。オブジェクトのすべてのプロパティを行ごとに定義する必要があります。他の方法はより簡単で、オブジェクトを作成するためのコードが少なくなりますが、場合によっては注意する必要があります。私は常に「他の方法」を使用していますが、最善の方法を使用しない場合は、上記の警告に対する1つの解決策は次のとおりです。

 for (var property in new_object) {
  if (new_object.hasOwnProperty(property)) {
    // ... this is an own property
  }
 }

0

主にオブジェクトを作成するには3つの方法があります。

最も簡単な方法は、オブジェクトリテラルを使用することです。

const myObject = {}

この方法は最も簡単ですが、欠点があります。つまり、オブジェクトに動作(関数)がある場合、将来変更を加えたい場合は、すべてのオブジェクトで変更する必要があります

したがって、その場合は、ファクトリ関数またはコンストラクタ関数を使用することをお勧めします。

ファクトリ関数は、オブジェクトを返す関数です。

function factoryFunc(exampleValue){
   return{
      exampleProperty: exampleValue 
   }
}

コンストラクタ関数は、「this」キーワードを使用してオブジェクトにプロパティを割り当てる関数です。eg-

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.