Який спосіб найкраще створити об’єкт у JavaScript? Чи потрібна `var` перед властивістю об'єкта?


177

Поки я бачив три способи створення об’єкта в JavaScript. Який спосіб найкращий для створення об’єкта і чому?

Я також бачив, що в усіх цих прикладах ключове слово varне використовується перед властивістю - чому? Чи не потрібно оголошувати varперед назвою властивості, оскільки вона згадувала, що властивості є змінними?

У другому та третьому способах ім'я об’єкта є великим, тоді як у першому - ім'я об'єкта в нижньому регістрі. Який випадок слід використовувати для імені об’єкта?

Перший спосіб:

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.");

Другий спосіб:

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

Robot.killAllHumans();

Третій спосіб - об’єкти JavaScript, що використовують синтаксис масиву:

var NewObject = {};

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

2
"var" використовується залежно від сфери змінної, визначає глобальну чи ні, шукайте її, і ви побачите різницю.
jackJoe

80
якщо ви створюєте самовбивчих роботів, завжди використовуйте var, будь ласка, .. опускання це робить їх глобальними
mykhal

9
"var використовується в залежності від сфери використання змінної" - така практика BAD - її слід використовувати незалежно від того, в якій області ви знаходитесь
treecoder

1
Що з методом Object.create():?
Макс

Було б добре, якби "як було зазначено, що властивості є змінними" було уточнено. Хто там"? Де це згадується? Чи можете ви навести конкретну цитату?
user4642212

Відповіді:


181

Не існує найкращого способу, це залежить від вашого випадку використання.

  • Використовуйте спосіб 1, якщо ви хочете створити кілька подібних об'єктів. У вашому прикладі Person(ви повинні почати ім'я з великої літери) називається функцією конструктора . Це схоже на класи інших мов ОО.
  • Використовуйте спосіб 2, якщо вам потрібен лише один об’єкт такого роду (як синглтон). Якщо ви хочете, щоб цей об’єкт успадкував інший, тоді вам доведеться використовувати конструкторську функцію.
  • Використовуйте спосіб 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 = нова людина ("gazy", "Doe", 45, "коричневий"); myBrother = нова людина ("опитування", "Doe", 15, "синій");
Jamna

Я думаю, ти маєш на увазі obj [ім'я] = 42. Так?
Кіт Пінсон

Я хотів би зазначити, що параметри 2 і 3 практично однакові, просто ви присвоюєте властивості після створення об'єкта. Це те, що називається буквальним позначенням , оскільки ви використовуєте об'єкт літерал для створення свого об'єкта. Під кришкою це фактично називає "новий об'єкт ()". Ви можете більш прочитати про це тут: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide / ...
dudewad

У другому випадку, чи було б сенсом, якби ми використовували оператор розповсюдження ...для успадкування від іншого об’єкта?
6пак малюк

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"
} 

Ви можете спробувати його на консолі, якщо у вас є плутанина.


HEy @Alex_Nabu - я вже поділився прикладами у своєму дописі. Якщо ви все ще стикаєтесь із будь-якими проблемами, будь ласка, оновіть мене, я допоможу вам.
Anand Deep Singh

1
хіба не було б більше сенсу будувати кожен приклад, даючи var personзрештою той самий екземпляр? наприклад, у конструкторі функцій ви можете просто додати var person = new Person("Anand"). а що з наче випадковим використанням напівколонки? : P
Крегокс

2
Це додало б значення, що пояснює плюси та мінуси кожного способу.
RayLoveless

10

Не існує "найкращого способу" створення об'єкта. Кожен спосіб має переваги залежно від вашого випадку використання.

Шаблон конструктора (функція, сполучена з new оператором, щоб викликати його) забезпечує можливість використання спадкового прототипу, тоді як інші способи цього не роблять. Отже, якщо ви хочете успадкувати прототипи, то функція конструктора - це чудовий шлях.

Однак, якщо ви хочете прототипічного успадкування, ви можете також використовувати Object.create, що робить спадщину більш очевидною.

Створення об'єкта буквально (наприклад var obj = {foo: "bar"};:) чудово працює, якщо у вас є всі властивості, які ви хочете встановити під час створення.

Для встановлення властивостей пізніше NewObject.property1синтаксис переважно кращий, NewObject['property1']якщо ви знаєте ім'я властивості. Але остання корисна, якщо ви фактично не маєте назви ресурсу достроково (наприклад:NewObject[someStringVar] .

Сподіваюся, це допомагає!


6

Я думаю, це залежить від того, що ти хочеш. Для простих об'єктів, я думаю, ви могли б використовувати другі методи. Коли ваші об'єкти збільшуються, і ви плануєте використовувати подібні об'єкти, я думаю, перший метод був би кращим. Таким чином ви також можете розширити його за допомогою прототипів.

Приклад:

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;
}

Я не є великим прихильником третього методу, але він дійсно корисний, наприклад, для динамічного редагування властивостей, наприклад var foo='bar'; var bar = someObject[foo];.


3

Існує багато способів створення ваших об'єктів в JavaScript. Використання функції конструктора для створення об'єкта або об'єкта буквальне позначення використовує багато в JavaScript. Крім того, створюючи екземпляр Object, а потім додаючи до нього властивості та методи, існує три загальних способи створення об’єктів у JavaScript.

Функції конструктора

Є вбудовані функції конструктора, які всі ми можемо використовувати їх час від часу, як дата (), число (), булевий () тощо, усі функції конструктора починаються з великої літери, тим часом ми можемо створити власну функцію конструктора в 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
};  

Прототипування

Створивши Object, ви можете прототипувати більше членів до цього, наприклад, додаючи колір до нашого поля, ми можемо це зробити:

Box.prototype.colour = 'red';

2

Хоча багато людей тут говорять, що немає найкращого способу створення об’єктів, існує обґрунтування того, чому існує так багато способів створення об’єктів у JavaScript на 2019 рік, і це пов'язано з прогресом JavaScript за різними ітераціями випусків EcmaScript з 1997 року.

До ECMAScript 5 існували лише два способи створення об'єктів: конструкторська функція або буквальне позначення (краща альтернатива новому об’єкту ()). За допомогою позначення функції конструктора ви створюєте об'єкт, який можна інстанціювати в декілька екземплярів (за допомогою нового ключового слова), тоді як буквальне позначення доставляє один об'єкт, як синглтон.

// 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". За умовою, ідентифікатор функції пишеться з великої літери, але він не потрібен. Всередині конструктора ми посилаємось на ключове слово "це", щоб додати властивості до об'єкта, який функція конструктора неявно створює. Функція конструктора неявно повертає новий об'єкт із заповненими властивостями назад в функцію виклику неявно, якщо ви явно не використовуєте ключове слово 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

Те, як ми використали прототип ланцюга вище, має вигадку. Оскільки прототип є живою ланкою, змінюючи властивість одного об'єкта в ланцюзі прототипу, ви також будете змінювати те саме властивість іншого об'єкта. Очевидно, що зміна успадкованого методу дитини не повинна змінювати метод батьків. Object.create вирішив цю проблему, використовуючи polyfill. Таким чином, за допомогою 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

Загалом ці 5 різних стратегій створення об’єктів у JavaScript співпадали з еволюцією стандарту 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

У наведеному вище прикладі журнал виведе помилковий.

Тепер давайте розберемося, чому інші способи створення об’єктів неправильні.

//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 true. Що означає, якщо у вас є випадок, що у вас є for inцикл, щоб побачити, чи є об'єкт властивістю, ймовірно, ви приведете до неправильних результатів.

Зауважте, що найкращий спосіб це непросто. Вам потрібно визначити всі властивості об'єкта по рядку. Інші способи простіші та матимуть менше коду для створення об’єкта, але вам потрібно бути в курсі деяких випадків. Я завжди використовую "інші способи" до речі, і одне рішення вищезазначеного попередження, якщо ви використовуєте не найкращий спосіб, це:

 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 
   }
}

Функції конструктора - це ті функції, які присвоюють властивості об’єктам, використовуючи ключове слово "це".

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.