Кратко
СкопированоКроме примитивных типов в 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' }
⚠️ Следует избегать изменения прототипа у существующего объекта, так как это сильно снижает производительность.