Какой способ лучше всего подходит для создания объекта в JavaScript? Нужно ли `var` перед свойством объекта? - PullRequest
169 голосов
/ 27 июля 2011

До сих пор я видел три способа создания объекта в 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 */ }

Ответы [ 8 ]

173 голосов
/ 27 июля 2011

Нет способа лучший , это зависит от вашего варианта использования.

  • Используйте способ 1 , если вы хотите создать несколько похожих объектов.В вашем примере Person (имя должно начинаться с заглавной буквы) называется функцией конструктора .Это похоже на классы в других языках OO.
  • Используйте way 2 , если вам нужен один объект вида (например, синглтон)).Если вы хотите, чтобы этот объект наследовал от другого, вам необходимо использовать функцию конструктора.
  • Используйте way 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;
110 голосов
/ 07 мая 2015

Существует несколько способов определения функции. Это полностью основано на вашем требовании. Ниже приведены несколько стилей: -

  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. Singleton
var person = new function(){
  this.name = "Anand"
} 

Вы можете попробовать это на консоли, если у вас возникли какие-либо сомнения.

10 голосов
/ 27 июля 2011

Нет лучшего способа создать объект.Каждый способ имеет свои преимущества в зависимости от вашего варианта использования.

Шаблон конструктора (функция в паре с оператором new для его вызова) предоставляет возможность использования наследования прототипа, тогда как другие способы этого не делают.Так что, если вы хотите наследование прототипа, то функция конструктора - отличный способ.

Однако, если вы хотите наследование прототипа, вы также можете использовать Object.create, что делаетнаследование более очевидно.

Создание литерала объекта (например: var obj = {foo: "bar"};) прекрасно работает, если у вас есть все свойства, которые вы хотите установить под рукой во время создания.

Для установки свойствпозже синтаксис NewObject.property1 обычно предпочтительнее NewObject['property1'], если вы знаете имя свойства.Но последнее полезно, когда у вас нет имени свойства заранее (например: NewObject[someStringVar]).

Надеюсь, это поможет!

6 голосов
/ 27 июля 2011

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

Пример:

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 голосов
/ 28 мая 2017

Существует множество способов создания ваших объектов в JavaScript.Использование функции конструктора для создания объекта или буквенной нотации объекта использует alot в JavaScript.Кроме того, создавая экземпляр объекта, а затем добавляя к нему свойства и методы, существует три распространенных способа создания объектов в JavaScript.

Функции конструктора

Есть встроенные-в функциях конструктора, которые мы все время от времени можем использовать, например 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';
0 голосов
/ 23 июня 2019

Хотя многие здесь говорят, что нет лучшего способа создания объектов, существует разумное объяснение, почему существует так много способов создания объектов в JavaScript, начиная с 2019 года, и это связано с прогрессом JavaScript над различные версии релизов EcmaScript, начиная с 1997 года.

До ECMAScript 5 существовало только два способа создания объектов: функция конструктора или литеральная запись (лучшая альтернатива 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

То, как мы использовали вышеописанную цепочку прототипов, имеет причуду. Поскольку прототип является действующей ссылкой, изменяя свойство одного объекта в цепочке прототипов, вы также изменили бы то же свойство другого объекта. Очевидно, что изменение наследуемого метода ребенка не должно изменять метод родителя. 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

В целом, эти 5 различных стратегий создания объектов в JavaScript совпали с развитием стандарта EcmaScript.

0 голосов
/ 02 февраля 2019

В основном есть 3 способа создания Объектов -

Самый простой - это использование литералов объектов .

const myObject = {}

Хотя этот метод самый простой, ноимеет недостаток, т. е. если ваш объект имеет поведение (функции в нем), то в будущем, если вы захотите внести в него какие-либо изменения, вам придется изменить его во всех объектах .

Так что в этомВ этом случае лучше использовать фабричные или конструкторские функции (любой, кто вам нравится)

фабричные функции - это те функции, которые возвращают object.eg-

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

Функции конструктора - это те функции, которые присваивают свойства объектам, используя ключевое слово "this" .eg-

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
0 голосов
/ 08 июня 2018

Конечно, есть лучший способ. Объекты в 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, чтобы увидеть,у объекта есть свойство, которое, вероятно, приведет к неправильным результатам.

Обратите внимание, что лучше всего это не легко. Вам нужно построчно определять все свойства объекта. Другие способыэто проще и будет иметь меньше кода для создания объекта, но вы должны знать об этом в некоторых случаях.Между прочим, я всегда использую «другие способы», и одним из решений вышеупомянутого предупреждения, если вы не используете лучший способ, является:

 for (var property in new_object) {
  if (new_object.hasOwnProperty(property)) {
    // ... this is an own property
  }
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...