Кратко
СкопированоКроме примитивных типов в 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
, совершенно идентичны.
Чтение свойств
СкопированоСуществует два вида синтаксиса для обращения к значению свойства объекта. В обоих случаях используется имя свойства.
Самый распространённый способ — с помощью точки:
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 // }
Имена свойств
СкопированоИмена свойств (иногда их называют ключи, или поля) могут быть либо строками, либо символами. Если использовать в качестве ключа другой тип данных, то он будет приведён к строке с помощью вызова метода to
:
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
.
🛠 Для копирования объектов используется спред-синтаксис:
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);
Разберёмся, как выполняется этот код.
- В начале переменные
mouse
иcat
указывают на собственные объекты. - В строке
mouse
мы присваиваем переменной mouse ссылку на объект cat. Можно рассматривать это как "связывание" переменных. Теперь обе переменные указывают на один и тот же объект= cat { name
.: ' Tom' , is Hunter : true} - Теперь
mouse
и. name cat
будут менять значения свойства одного и того же объекта.. name - Последнее изменение в этом объекте происходит присваиванием значения
undefined
ключуis
.Hunter - Выводя в консоль значение ключа
is
, получим последнее его обновление —Hunter undefined
.
Такой способ рассуждения классно описан в книге "Just JavaScript" Дэна Абрамова. Он предлагает метафору, где имена переменных связываются проводами с данными в них, а ключи в объектах представляются как провода с подписями. Когда вы меняете значения в объектах или переназначаете связи объектов и переменных, вы просто переключаете провода из одного штекера в другой.
let cat
mouse
Такие же рассуждения подходят и для более сложных случаев:
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
. После переменная 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
используется срабатывают два правила:
- При вызове
return
с объектом, вместоthis
вернётся этот объект. - При вызове
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; }; };
отвечает
СкопированоНачнём с лаконичного определения, зафиксированного в спецификации ECMAScript:
Прототип — это объект, предоставляющий другим объектам общие (shared) свойства.
В свою очередь MDN определяет прототипы как механизм, благодаря которому объекты получают доступ (inherit) к свойствам (features) других объектов.
Прототип позволяет указать какие свойства будут доступны созданным от него объектам, а также предоставляет доступ к своему собственному прототипу.
При попытке обратиться к свойству, которое не определено в самом объекте, производится поиск в прототипе объекта, а затем в прототипе прототипа и далее, пока искомое свойство не будет найдено или не будет достигнут конец цепочки прототипов (prototype chain), так как у базового объекта Object
прототипом является null
.
У каждого объекта есть встроенное свойство, указывающее на его прототип. Попробуем его получить напрямую:
☝️ При запуске console
в 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
возвращает прототип объекта.
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
будут доступны в объекте my
, даже если эти изменения произойдут после создания объекта my
.
- Когда объект создаётся с помощью конструктора, прототип объекта назначается в соответствии со значением поля
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
. Свойство is
наследуется, хотя было добавлено в Bear
уже после создания объекта panda
.
💡 Статический метод Object
проверяет, являются ли переданные ему в качестве аргументов значения идентичными.
- Когда объект создаётся как экземпляр класса, прототип объекта назначается в соответствии со значением поля
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
☝️ Обратите внимание: свойство get
не наследуется объектом person
, а свойство set
наследуется, хотя было добавлено в Person.prototype уже после создания объекта person
.
Возможно ли изменить прототип созданного объекта?
Да, но крайне не рекомендуется. Для этого можно использовать метод set
:
// Объект-прототип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' }
⚠️ Следует избегать изменения прототипа у существующего объекта, так как это сильно снижает производительность.