Объект

Непримитивный тип данных. Представляет собой набор свойств.

Время чтения: 6 мин

Кратко

Скопировано

Кроме примитивных типов в JavaScript существуют и сложные — например, объект.

Объект (object) — это набор свойств. Каждое свойство состоит из названия и значения. Название может быть строкой или символом, а значение может быть любым.

Объекты в JavaScript используются повсюду, особенно для хранения данных. Для уверенной работы с объектами необходимо знать, как создавать объект, как его изменять и как читать значения свойств.

Создание объектов

Скопировано

Чаще всего объекты создают с помощью литеральной записи.

Пустой объект без свойств можно создать парой фигурных скобок:

        
          
          const cat = {}
          const cat = {}

        
        
          
        
      

Когда нужно создать объект со свойствами, то их описывают внутри фигурных скобок. Свойства указываются в формате имяСвойства : значение, между свойствами ставится запятая:

        
          
          const book = {  title: 'Война и мир',  author: 'Лев Толстой',  pages: 1274,  isFinished: true}
          const book = {
  title: 'Война и мир',
  author: 'Лев Толстой',
  pages: 1274,
  isFinished: true
}

        
        
          
        
      

Значением может быть другой объект или массив:

        
          
          const cat = {  kittens: ['Беляш', 'Михаил', 'Чарли'],  favoriteToy: {    name: 'мячик',    size: 'маленький',  },}
          const cat = {
  kittens: ['Беляш', 'Михаил', 'Чарли'],
  favoriteToy: {
    name: 'мячик',
    size: 'маленький',
  },
}

        
        
          
        
      

Или даже функция:

        
          
          const cat = {  name: 'Том',  meow: function () {    console.log('мяу мяу')  },}cat.meow()// мяу мяу
          const cat = {
  name: 'Том',
  meow: function () {
    console.log('мяу мяу')
  },
}

cat.meow()
// мяу мяу

        
        
          
        
      

Свойства можно добавлять и после создания объекта:

        
          
          const cat = {}cat.name = 'Simon'cat.gender = 'male'cat.color = 'brown'cat.age = 2cat.adorable = trueconsole.log(cat)// {//   name: 'Simon',//   gender: 'male',//   color: 'brown',//   age: 2,//   adorable: true// }
          const cat = {}
cat.name = 'Simon'
cat.gender = 'male'
cat.color = 'brown'
cat.age = 2
cat.adorable = true

console.log(cat)
// {
//   name: 'Simon',
//   gender: 'male',
//   color: 'brown',
//   age: 2,
//   adorable: true
// }

        
        
          
        
      

Создать объект также можно с помощью конструктора Object. Это объектно-ориентированный стиль программирования:

        
          
          const book = new Object({ title: 'Война и мир', author: 'Лев Толстой' })
          const book = new Object({ title: 'Война и мир', author: 'Лев Толстой' })

        
        
          
        
      

Объекты, созданные через фигурные скобки и через new Object() совершенно идентичны.

Чтение свойств

Скопировано

Существует два вида синтаксиса для обращения к значению свойства объекта, в обоих случаях используется имя свойства.

Самый распространённый способ — с помощью точки:

        
          
          console.log(`На полке стоит «${book.title}»`)// На полке стоит «Война и мир»const pagesPerDay = book.pages / 365console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)// Чтобы прочитать её за год, читайте 3.5 страницы в день
          console.log(`На полке стоит «${book.title}»`)
// На полке стоит «Война и мир»

const pagesPerDay = book.pages / 365
console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)
// Чтобы прочитать её за год, читайте 3.5 страницы в день

        
        
          
        
      

Альтернативно для чтения можно использовать квадратные скобки:

        
          
          console.log(`На полке стоит «${book['title']}»`)const pagesPerDay = book['pages'] / 365console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)
          console.log(`На полке стоит «${book['title']}»`)

const pagesPerDay = book['pages'] / 365
console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)

        
        
          
        
      

Если прочитать свойство, которого нет у объекта, то вернётся undefined:

        
          
          const signature = book.signatureconsole.log(signature)// undefined
          const signature = book.signature

console.log(signature)
// undefined

        
        
          
        
      

Добавление и изменение свойств

Скопировано

Созданный объект можно изменять — добавлять, изменять и удалять свойства.

Для добавления и изменения свойств используется одинаковый синтаксис. Нужно обратиться к свойству и присвоить в него значение с помощью стандартного оператора присваивания =. Если свойство не существует, оно будет создано:

        
          
          const book = {  title: 'Капитанская дочка'}// добавляем новое свойствоbook.author = 'А.С.Пушкин'// изменяем существующееbook.title = 'Сказка о царе Салтане'console.log(book)// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
          const book = {
  title: 'Капитанская дочка'
}

// добавляем новое свойство
book.author = 'А.С.Пушкин'

// изменяем существующее
book.title = 'Сказка о царе Салтане'

console.log(book)
// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}

        
        
          
        
      

Синтаксис с квадратными скобками работает и здесь:

        
          
          const book = {  title: 'Капитанская дочка'}// добавляем новое свойствоbook['author'] = 'А.С.Пушкин'// изменяем существующееbook['title'] = 'Сказка о царе Салтане'console.log(book)// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
          const book = {
  title: 'Капитанская дочка'
}

// добавляем новое свойство
book['author'] = 'А.С.Пушкин'

// изменяем существующее
book['title'] = 'Сказка о царе Салтане'

console.log(book)
// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}

        
        
          
        
      

Удаление свойств

Скопировано

Для удаления свойств используют оператор delete:

        
          
          const book = {  title: 'Война и мир',  author: 'Лев Толстой',  pages: 1274,  isFinished: true,  usersReading: [1946, 1293, 7743]}delete book.usersReadingdelete book['isFinished']console.log(book)// { title: 'Война и мир', author: 'Лев Толстой', pages: 1274 }
          const book = {
  title: 'Война и мир',
  author: 'Лев Толстой',
  pages: 1274,
  isFinished: true,
  usersReading: [1946, 1293, 7743]
}

delete book.usersReading
delete book['isFinished']

console.log(book)
// { title: 'Война и мир', author: 'Лев Толстой', pages: 1274 }

        
        
          
        
      

Чаще всего свойства не удаляют, а сбрасывают значение, устанавливая undefined или подходящее по смыслу:

        
          
          const book = {  title: 'Война и мир',  author: 'Лев Толстой',  pages: 1274,  isFinished: true,  usersReading: [1946, 1293, 7743]}book.usersReading = undefinedbook['isFinished'] = undefined// {//    title: 'Война и мир',//    author: 'Лев Толстой',//    pages: 1274//    isFinished: undefined,//    usersReading: undefined// }
          const book = {
  title: 'Война и мир',
  author: 'Лев Толстой',
  pages: 1274,
  isFinished: true,
  usersReading: [1946, 1293, 7743]
}

book.usersReading = undefined
book['isFinished'] = undefined
// {
//    title: 'Война и мир',
//    author: 'Лев Толстой',
//    pages: 1274
//    isFinished: undefined,
//    usersReading: undefined
// }

        
        
          
        
      

Имена свойств

Скопировано

Имена свойств (иногда их называют ключи, или поля) могут быть либо строками, либо символами. Если использовать в качестве ключа другой тип данных, то он будет приведён к строке с помощью вызова метода toString():

        
          
          const obj = {}const key = {}obj[key] = 'value for the object key'console.log(obj)// { '[object Object]': 'value for the object key' }
          const obj = {}
const key = {}
obj[key] = 'value for the object key'

console.log(obj)
// { '[object Object]': 'value for the object key' }

        
        
          
        
      

Если ключ содержит пробел, то обращаться к нему возможно только через синтаксис квадратных скобок:

        
          
          const obj = {  'the answer': 42}console.log(obj['the answer'])// 42
          const obj = {
  'the answer': 42
}

console.log(obj['the answer'])
// 42

        
        
          
        
      

Сравнение объектов

Скопировано

Объекты — ссылочный тип данных. Сравнению по ссылке посвящена отдельная статья.

При сравнении двух объектов JavaScript сравнивает не значения свойств этих объектов, а адреса в памяти, по которым эти объекты хранятся. Поэтому любое сравнение двух объектов будет возвращать false, даже если они выглядят одинаково:

        
          
          // создаётся один объектconst book = { title: 'Дюна' }// создаётся другой объектconst anotherBook = { title: 'Дюна' }console.log(book === anotherBook)// false
          // создаётся один объект
const book = { title: 'Дюна' }
// создаётся другой объект
const anotherBook = { title: 'Дюна' }

console.log(book === anotherBook)
// false

        
        
          
        
      

Сравнение будет возвращать true, только если мы сравниваем переменные, указывающие на один и тот же объект:

        
          
          // создаётся один объектconst book = { title: 'Дюна' }// в anotherBook записывается ссылка на объектconst anotherBook = bookconsole.log(book === anotherBook)// true
          // создаётся один объект
const book = { title: 'Дюна' }
// в anotherBook записывается ссылка на объект
const anotherBook = book

console.log(book === anotherBook)
// true

        
        
          
        
      

На практике

Скопировано

Дока Дог советует

Скопировано

🛠 Современные версии JavaScript содержат много упрощений синтаксиса.

Например, методы объявлять по-старому:

        
          
          const cat = {  name: 'Том',  meow: function () {    console.log('мяу мяу')  },}
          const cat = {
  name: 'Том',
  meow: function () {
    console.log('мяу мяу')
  },
}

        
        
          
        
      

А можно использовать короткий синтаксис:

        
          
          const cat = {  name: 'Том',  meow() {    console.log('мяу мяу')  },}
          const cat = {
  name: 'Том',
  meow() {
    console.log('мяу мяу')
  },
}

        
        
          
        
      

Если у вас есть переменная со значением, и вы хотите создать свойство с тем же именем, то вместо старого подхода:

        
          
          const firstName = 'Иван'const username = 'Killer3000'const user = {  firstName: firstName,  username: username}console.log(user)// { firstName: 'Иван', username: 'Killer3000' }
          const firstName = 'Иван'
const username = 'Killer3000'

const user = {
  firstName: firstName,
  username: username
}

console.log(user)
// { firstName: 'Иван', username: 'Killer3000' }

        
        
          
        
      

Можно сократить запись:

        
          
          const firstName = 'Иван'const username = 'Killer3000'const user = {  firstName,  username}console.log(user)// { firstName: 'Иван', username: 'Killer3000' }
          const firstName = 'Иван'
const username = 'Killer3000'

const user = {
  firstName,
  username
}

console.log(user)
// { firstName: 'Иван', username: 'Killer3000' }

        
        
          
        
      

🛠 Если название свойства хранится в переменной, его значение можно прочитать через синтаксис квадратных скобок:

        
          
          const user = {  firstName: 'Марина',  username: 'zloyDuh'}const prop = 'firstName'console.log(user[prop])// Марина
          const user = {
  firstName: 'Марина',
  username: 'zloyDuh'
}

const prop = 'firstName'
console.log(user[prop])
// Марина

        
        
          
        
      

🛠 Для проверки, есть ли свойство у объекта, используйте оператор in:

        
          
          const user = {  firstName: 'Марина',  username: 'zloyDuh'}console.log('firstName' in user)// trueconsole.log('age' in user)// false
          const user = {
  firstName: 'Марина',
  username: 'zloyDuh'
}

console.log('firstName' in user)
// true
console.log('age' in user)
// false

        
        
          
        
      

🛠 Чтобы обойти все ключи объекта, используют цикл for...in

🛠 Для копирования объектов используется спред-синтаксис:

        
          
          const user = {  firstName: 'Марина',  username: 'zloyDuh'}const copy = { ...user }console.log(copy)// { firstName: 'Марина', username: 'zloyDuh'}
          const user = {
  firstName: 'Марина',
  username: 'zloyDuh'
}

const copy = { ...user }
console.log(copy)
// { firstName: 'Марина', username: 'zloyDuh'}

        
        
          
        
      

При этом происходит поверхностное копирование — полностью копируются только свойства первого уровня вложенности. Подробнее об этом читайте статью «Поверхностное и глубокое копирование».

На собеседовании

Скопировано
Задать вопрос в рубрику
🤚 Я знаю ответ

Саша Патлух  отвечает

Скопировано

Что проверяют:

Это часто встречающаяся группа вопросов на собеседовании. Отличить её можно по таким признакам: вам предлагают два и более JS-объекта, в которых программно меняют свойства по ключам. Спрашивают, что в результате попадёт в консоль при вызове какого-то определённого ключа.

Так проверяют ваше знание того, что значения объектов передаются по ссылке и что ключи в объекте — это способ построить связь с конкретными данными.

Ответ:

Обычно перед вами будет пример, вроде такого:

        
          
          let cat = {  name: 'Tom',  isHunter: true}let mouse = {  name: 'Jerry',  isHunter: false}mouse = cat;cat.isHunter = false;mouse.isHunter = undefined;console.log(mouse.isHunter);
          let cat = {
  name: 'Tom',
  isHunter: true
}

let mouse = {
  name: 'Jerry',
  isHunter: false
}

mouse = cat;
cat.isHunter = false;
mouse.isHunter = undefined;

console.log(mouse.isHunter);

        
        
          
        
      

Разберёмся, как выполняется этот код.

  1. В начале переменные mouse и cat указывают на собственные объекты.
  2. В строке mouse = cat мы присваиваем переменной mouse ссылку на объект cat. Можно рассматривать это как "связывание" переменных. Теперь обе переменные указывают на один и тот же объект { name: 'Tom', isHunter: true}.
  3. Теперь mouse.name и cat.name будут менять значения свойства одного и того же объекта.
  4. Последнее изменение в этом объекте происходит присваиванием значения undefined ключу isHunter.
  5. Выводя в консоль значение ключа isHunter, получим последнее его обновление — undefined.

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

let cat = { name: 'Tom', isHunter: true}

Схема. Объект cat имеет свойство name со значением Tom и свойство isHunter со значением true

mouse = cat

Схема. В объект mouse присваивается объект cat со всеми свойствами и значениями

Такие же рассуждения подходят и для более сложных случаев:

        
          
          let cat = {  name: 'Tom',  isHunter: true}let mouse = {  name: 'Jerry',  isHunter: false}cat.isHunter = mouse.isHunter;mouse.isHunter = undefined;mouse = cat;console.log(mouse.isHunter);
          let cat = {
  name: 'Tom',
  isHunter: true
}

let mouse = {
  name: 'Jerry',
  isHunter: false
}

cat.isHunter = mouse.isHunter;
mouse.isHunter = undefined;
mouse = cat;

console.log(mouse.isHunter);

        
        
          
        
      

В этом примере в консоли будет false, ведь данные в объекте, который выводится в консоль, изменены только однажды в строке cat.isHunter = mouse.isHunter. После переменная mouse была «подключена» к тому же объекту, на который указывает переменная cat.

🤚 Я знаю ответ

Сергей Власов  отвечает

Скопировано

В первом случае просто была вызвана функция, которая ничего не возвращает. Значение переменной будет равно undefined

        
          
          const animal = Animal() // ❌console.log(animal) // undefined
          const animal = Animal() // ❌
console.log(animal) // undefined

        
        
          
        
      

Во втором случае перед функцией Animal стоит оператор new. Функция Animal становится конструктором. Она выполняется, но так как this внутри функции не используется, и сама функция ничего не возвращает, то ничего не происходит. Результатом операции становится новый объект, который ссылается на функцию Animal как на конструктор. Этот объект присваивается переменной animal

        
          
          const animal = new Animal() // ✅
          const animal = new Animal() // ✅

        
        
          
        
      

Если Animal имеет вид:

        
          
          function Animal() {  this.name = 'Cat'}
          function Animal() {
  this.name = 'Cat'
}

        
        
          
        
      

То переменная animal, созданная с помощью new, будет иметь доступ к полю name:

        
          
          console.log(animal)// Animal { name: 'Cat' }// Если мы явно не возвращаем ничего из конструктора,// то получаем сам объект в качестве результата.
          console.log(animal)
// Animal { name: 'Cat' }
// Если мы явно не возвращаем ничего из конструктора,
// то получаем сам объект в качестве результата.

        
        
          
        
      

Рассмотрим возврат значения из конструктора

Скопировано

Обычно в функции-конструкторе не используется оператор return. Если return используется срабатывают два правила:

  1. При вызове return с объектом, вместо this вернётся этот объект.
  2. При вызове return с пустым или с примитивным значением, оно будет проигнорировано.

return с объектом возвращает этот объект, во всех остальных случаях возвращается this

        
          
          function Animal() {  this.foo = 'BARBARBAR'  return {    foo: 'bar' // ⬅️ возвращает этот объект  }}const animal = new Animal()console.log(animal.foo)// Вернет `bar`
          function Animal() {
  this.foo = 'BARBARBAR'
  return {
    foo: 'bar' // ⬅️ возвращает этот объект
  }
}

const animal = new Animal()
console.log(animal.foo)
// Вернет `bar`

        
        
          
        
      

А вот пример с примитивом после return:

        
          
          function Animal() {  this.foo = 'BARBARBAR'  return 'bar' // ⬅️ возвращает this}const animal = new Animal()console.log(animal.foo)// Вернет BARBARBAR
          function Animal() {
  this.foo = 'BARBARBAR'
  return 'bar' // ⬅️ возвращает this
}

const animal = new Animal()
console.log(animal.foo)
// Вернет BARBARBAR

        
        
          
        
      
🤚 Я знаю ответ

Алекс Рассудихин  отвечает

Скопировано

Объект первого класса (first class object или first class citizen) это объект, который может быть передан как аргумент функции, возвращён из функции или присвоен переменной.

Функции в JavaScript полностью соответствуют этому определению.

Функцию можно присвоить переменной:

        
          
          const multipleTwo = (n) => n * 2;
          const multipleTwo = (n) => n * 2;

        
        
          
        
      

Функция может быть передаваемым аргументом другой функции:

        
          
          async function loadData(func) {  loading = true;  // другой код относящийся к инициализации статусов загрузки  await func();  loading = false;  // другой код относящийся к обработке статуса загрузки}function getData() {  // код получения данных с сервера}loadData(getData);
          async function loadData(func) {
  loading = true;
  // другой код относящийся к инициализации статусов загрузки

  await func();

  loading = false;
  // другой код относящийся к обработке статуса загрузки
}

function getData() {
  // код получения данных с сервера
}

loadData(getData);

        
        
          
        
      

Функции могут быть возвращаемым значением другой функции:

        
          
          function makeAdder(x) {  return function(y) {    return x + y;  };};
          function makeAdder(x) {
  return function(y) {
    return x + y;
  };
};

        
        
          
        
      
🤚 Я знаю ответ

Viktar Nezhbart  отвечает

Скопировано

Начнём с лаконичного определения, зафиксированного в спецификации ECMAScript:

Прототип — это объект, предоставляющий другим объектам общие (shared) свойства.

В свою очередь MDN определяет прототипы как механизм, благодаря которому объекты получают доступ (inherit) к свойствам (features) других объектов.

Прототип позволяет указать какие свойства будут доступны созданным от него объектам, а также предоставляет доступ к своему собственному прототипу.

При попытке обратиться к свойству, которое не определено в самом объекте, производится поиск в прототипе объекта, а затем в прототипе прототипа и далее, пока искомое свойство не будет найдено или не будет достигнут конец цепочки прототипов (prototype chain), так как у базового объекта Object.prototype прототипом является null.

У каждого объекта есть встроенное свойство, указывающее на его прототип. Попробуем его получить напрямую:

☝️ При запуске console.dir() в Node.js для просмотра скрытых свойств объекта потребуются дополнительные параметры. Здесь и далее приводятся результаты выполнения в Node.js.

        
          
          const obj = { name: 'Объект' }console.dir(obj.prototype, {showHidden: true, depth: 0 })// undefined
          const obj = { name: 'Объект' }
console.dir(obj.prototype, {showHidden: true, depth: 0 })
// undefined

        
        
          
        
      

Ничего не вышло. Дело в том, что для доступа к прототипу следует использовать специальные методы.

💡 Статический метод Object.getPrototypeOf() возвращает прототип объекта.

        
          
          const obj = { name: 'Объект' }console.dir(Object.getPrototypeOf(obj), {showHidden: true, depth: 0 })// [Object: null prototype] {//   [constructor]: [Function],//   [__defineGetter__]: [Function],//   [__defineSetter__]: [Function],//   [hasOwnProperty]: [Function],//   [__lookupGetter__]: [Function],//   [__lookupSetter__]: [Function],//   [isPrototypeOf]: [Function],//   [propertyIsEnumerable]: [Function],//   [toString]: [Function],//   [valueOf]: [Function],//   ['__proto__']: [Getter/Setter],//   [toLocaleString]: [Function]// }
          const obj = { name: 'Объект' }
console.dir(Object.getPrototypeOf(obj), {showHidden: true, depth: 0 })
// [Object: null prototype] {
//   [constructor]: [Function],
//   [__defineGetter__]: [Function],
//   [__defineSetter__]: [Function],
//   [hasOwnProperty]: [Function],
//   [__lookupGetter__]: [Function],
//   [__lookupSetter__]: [Function],
//   [isPrototypeOf]: [Function],
//   [propertyIsEnumerable]: [Function],
//   [toString]: [Function],
//   [valueOf]: [Function],
//   ['__proto__']: [Getter/Setter],
//   [toLocaleString]: [Function]
// }

        
        
          
        
      

Постойте, а как насчёт функций-конструкторов? Ведь они имеют свойство prototype доступное напрямую. Свойство prototype и прототип функции-конструктора (ведь функция это тоже объект) — это не одно и то же:

        
          
          // Функция-конструкторfunction Person(name) {  this.name = name;}console.dir(Person.prototype, {showHidden: true, depth: 0 })// { [constructor]: [Function] }console.dir(Object.getPrototypeOf(Person), {showHidden: true, depth: 0 })// {//   [length]: 0,//   [name]: '',//   [arguments]: [Getter/Setter],//   [caller]: [Getter/Setter],//   [constructor]: [Function],//   [apply]: [Function],//   [bind]: [Function],//   [call]: [Function],//   [toString]: [Function],//   [Symbol(Symbol.hasInstance)]: [Function]// }
          // Функция-конструктор
function Person(name) {
  this.name = name;
}

console.dir(Person.prototype, {showHidden: true, depth: 0 })
// { [constructor]: [Function] }

console.dir(Object.getPrototypeOf(Person), {showHidden: true, depth: 0 })
// {
//   [length]: 0,
//   [name]: '',
//   [arguments]: [Getter/Setter],
//   [caller]: [Getter/Setter],
//   [constructor]: [Function],
//   [apply]: [Function],
//   [bind]: [Function],
//   [call]: [Function],
//   [toString]: [Function],
//   [Symbol(Symbol.hasInstance)]: [Function]
// }

        
        
          
        
      

Свойство prototype у функции-конструктора используется для назначения прототипа объектам, которые будут созданы с помощью этого конструктора и никак не влияет на саму функцию-конструктор.

Как у объекта появляется прототип?

  • Прототип объекта можно указать при создании объекта с помощью Object.create():
        
          
          // Объект-прототипconst shape = { color: 'green' }// создадим новый объект на основе объекта-прототипаconst myShape = Object.create(shape)// Добавим свойство в объект-прототипshape.isCircle = true// Получим доступ к свойствуconsole.log(myShape.isCircle)// true
          // Объект-прототип
const shape = { color: 'green' }

// создадим новый объект на основе объекта-прототипа
const myShape = Object.create(shape)

// Добавим свойство в объект-прототип
shape.isCircle = true

// Получим доступ к свойству
console.log(myShape.isCircle)
// true

        
        
          
        
      

☝️ Обратите внимание: все изменения объекта-прототипа shape будут доступны в объекте myShape, даже если эти изменения произойдут после создания объекта myShape.

  • Когда объект создаётся с помощью конструктора, прототип объекта назначается в соответствии со значением поля prototype функции-конструктора:
        
          
          // Функция-конструкторfunction Bear(name) {  this.name = name}// Добавим свойство в BearBear.id = 'медведь'// Создадим новый объектconst panda = new Bear('Панда')// Получим прототип объектаconst pandaPrototype = Object.getPrototypeOf(panda)// А теперь добавим свойство в Bear.prototypeBear.prototype.isBear = true;// Отобразим свойства созданного объектаconsole.dir(panda, {showHidden: true })// Bear { name: 'Панда', isBear: true }// Убедимся, что свойство prototype конструктора является прототипом объектаconsole.log(Object.is(Bear.prototype, pandaPrototype))// true// Убедимся, что свойство prototype и прототип конструктора это не одно и то жеconsole.log(Object.is(Bear.prototype, Object.getPrototypeOf(Bear))// false
          // Функция-конструктор
function Bear(name) {
  this.name = name
}

// Добавим свойство в Bear
Bear.id = 'медведь'

// Создадим новый объект
const panda = new Bear('Панда')

// Получим прототип объекта
const pandaPrototype = Object.getPrototypeOf(panda)

// А теперь добавим свойство в Bear.prototype
Bear.prototype.isBear = true;

// Отобразим свойства созданного объекта
console.dir(panda, {showHidden: true })
// Bear { name: 'Панда', isBear: true }

// Убедимся, что свойство prototype конструктора является прототипом объекта
console.log(Object.is(Bear.prototype, pandaPrototype))
// true

// Убедимся, что свойство prototype и прототип конструктора это не одно и то же
console.log(Object.is(Bear.prototype, Object.getPrototypeOf(Bear))
// false

        
        
          
        
      

☝️ Обратите внимание: свойство id не наследуется объектом panda, потому что находится в самом объекте Bear. Свойство isBear наследуется, хотя было добавлено в Bear.prototype уже после создания объекта panda.

💡 Статический метод Object.is() проверяет, являются ли переданные ему в качестве аргументов значения идентичными.

  • Когда объект создаётся как экземпляр класса, прототип объекта назначается в соответствии со значением поля prototype объекта родительского класса:
        
          
          // Родительский классclass Person {  constructor(name) {    this.name = name  }}// Добавим метод в объект родительского классаPerson.getSkill = function() {  return this.skill}// Создадим экземпляр классаconst person = new Person('Иван')// Добавим свойство в Person.prototypePerson.prototype.setSkill = function(skill) {  this.skill = skill}// Добавим Ивану умение работать курьеромperson.setSkill('Курьер')// Получим прототип объектаconst proto = Object.getPrototypeOf(person)// Отобразим свойства созданного объектаconsole.dir(person, {showHidden: true})// Person { name: 'Иван', skill: 'Курьер' }// Убедимся, что свойство Person.prototype является прототипом объектаconsole.log(Object.is(Person.prototype, proto))// true
          // Родительский класс
class Person {
  constructor(name) {
    this.name = name
  }
}

// Добавим метод в объект родительского класса
Person.getSkill = function() {
  return this.skill
}

// Создадим экземпляр класса
const person = new Person('Иван')

// Добавим свойство в Person.prototype
Person.prototype.setSkill = function(skill) {
  this.skill = skill
}

// Добавим Ивану умение работать курьером
person.setSkill('Курьер')

// Получим прототип объекта
const proto = Object.getPrototypeOf(person)

// Отобразим свойства созданного объекта
console.dir(person, {showHidden: true})
// Person { name: 'Иван', skill: 'Курьер' }

// Убедимся, что свойство Person.prototype является прототипом объекта
console.log(Object.is(Person.prototype, proto))
// true

        
        
          
        
      

☝️ Обратите внимание: свойство getSkill не наследуется объектом person, а свойство setSkill наследуется, хотя было добавлено в Person.prototype уже после создания объекта person.

Возможно ли изменить прототип созданного объекта?

Да, но крайне не рекомендуется. Для этого можно использовать метод setPrototypeOf():

        
          
          // Объект-прототипconst pants = {  color: 'black',  showInfo: () => console.log('Брюки')}// Создадим новый объектconst myPants = Object.create(pants)myPants.size = 48myPants.showInfo()// Брюкиconsole.dir(myPants, {showHidden: true, depth: 0 })// { size: 48, color: 'black' }// Новый объект-прототипconst shorts = {  color: 'white',  showInfo: () => console.log('Элегантные шорты')};// Брюки превращаются…Object.setPrototypeOf(myPants, shorts)myPants.showInfo()// Элегантные шортыconsole.dir(myPants, {showHidden: true, depth: 0 })// { size: 48, color: 'white' }
          // Объект-прототип
const pants = {
  color: 'black',
  showInfo: () => console.log('Брюки')
}

// Создадим новый объект
const myPants = Object.create(pants)

myPants.size = 48
myPants.showInfo()
// Брюки

console.dir(myPants, {showHidden: true, depth: 0 })
// { size: 48, color: 'black' }

// Новый объект-прототип
const shorts = {
  color: 'white',
  showInfo: () => console.log('Элегантные шорты')
};

// Брюки превращаются…
Object.setPrototypeOf(myPants, shorts)

myPants.showInfo()
// Элегантные шорты

console.dir(myPants, {showHidden: true, depth: 0 })
// { size: 48, color: 'white' }

        
        
          
        
      

⚠️ Следует избегать изменения прототипа у существующего объекта, так как это сильно снижает производительность.