| title | Занятие 6 |
|---|---|
| description | Объектная модель в Javascript. Прототипное наследование |
let i = 1;
let j = 1;
i = 2;
console.log(i, j); // ?let a = {};
let b = {};
a.name = "Bob";
console.log(a.name, b.name); // ?let a = {};
let b = a;
a.name = "Bob";
console.log(a.name, b.name); // ?let a = [];
let b = a;
a.push("Bob");
console.log(a[0], b[0]); // ?- "Говорящее название"
- Переменная - существительное (исключение - булевы переменные)
- Функция/метод - глагол
- Булевы значения -
isA,hasB - Возможно использование венгерской нотации (
sText,nCount)
- camelCase - для переменных и полей объектов/классов
- PascalCase - для классов, конструкторов и пространств имен
- UPPER_CASE - для констант (не неизменяемых переменных, а конфигурационных значений)
- _secretField - уже не используется, но помнить стоит
- Структура данных - набор пар вида "ключ - значение"
- Ключи - String | Symbol
- Ссылочный тип данных
// Создание объекта 1
// через литерал
let o1 = {};
let o2 = {
prop1: "Some value",
prop2: null,
prop3: 3,
};// Создание объекта 2
// Вызвать функцию возвращающую объект
let o3 = Object.create(null);// Создание объекта 3
// Использовать `new` с классом или функцией-конструктором
let o4 = new Object();
let o5 = new Object({
a: 1,
b: 2,
});Какие есть способы работы со свойствами?
let o = {};
// точечная нотация
o.prop1 = 1;
console.log(o.prop1);
delete o.prop1;
// скобочная нотация
o["prop2"] = 2;
console.log(o["prop2"]);
delete o["prop2"];let o = {
x: 1,
};
console.log(o.x); // ?
let a = "x";
o.a = 2;
console.log(o.a, o[a]); // ?
let b = "x";
o["b"] = 3;
console.log(o.b, o[b]); // ?let o = {
prop1: 2,
};
console.log(o);
console.log(o.prop1); //?
console.log(o.prop2); // ?let o = {
someMethod: function () {
console.log("Hey!");
},
};
console.log(o);
console.log(o.someMethod); //?
console.log(o.toString); // ?let o = {
someMethod: function () {
console.log("Hey!");
},
};
console.log(o);
console.log(o.someMethod()); //?
console.log(o.toString()); // ?
console.log(o.someOtherMethod()); //?При обращении к свойству объекта:
- свойство ищется в самом объекте
- если свойство не найдено, делается поиск в прототипе объекта
- если свойство не найдено в прототипе, делается поиск дальше по цепочке прототипов, пока цепочка не закончится
let o = {
prop1: 1,
__proto__: {
prop2: 2,
},
};
console.log(o);
console.log(o.prop1); //?
console.log(o.prop2); //?
console.log(o.prop3); //?let o = {
prop1: 1,
__proto__: {
prop2: 2,
__proto__: {
prop3: 3,
},
},
};
console.log(o);
console.log(o.prop1); //?
console.log(o.prop2); //?
console.log(o.prop3); //?let o = {
prop1: 1,
__proto__: {
prop1: 2,
},
};
console.log(o);
console.log(o.prop1); //?
console.log(o.prop2); //?Запись свойств, всегда производится в сам объект (тот, что находится перед последней точкой, в точечной нотации). Независимо от того, есть свойство в объекте или нет.
let o = { __proto__: { prop1: 1 } };
console.log(o.prop1, o.__proto__.prop1); // ?
o.prop1 = 2;
console.log(o.prop1, o.__proto__.prop1); // ?
o["prop1"] = 3;
console.log(o.prop1, o.__proto__.prop1); // ?let proto = { prop0: 1 };
let o1 = { prop1: 1, __proto__: proto };
let o2 = { prop2: 2, __proto__: proto };
console.log(o1.prop0, o2.prop0); // ?
proto.prop0 = 5;
console.log(o1.prop0, o2.prop0); // ?
o2.prop0 = 7;
console.log(o1.prop0, o2.prop0); // ?
console.log(proto.prop0); // ?let proto = { settings: { isAdmin: false } };
let u1 = { name: "Bob", __proto__: proto };
let u2 = { name: "Sam", __proto__: proto };
console.log(u1.settings.isAdmin); // ?
u1.settings.isAdmin = true;
console.log(u1.settings.isAdmin); // ?
console.log(u2.settings.isAdmin); // ?Задание прототипа:
- прямая работа с
__proto__ Object.setPrototypeOf()Object.create(proto[, propertiesObject])- использование конструкторов
for(let x in obj){}- получить список свойств и проитерироваться по нему - keys, values, entries (но не в IE!)
let o = {
prop1: 1,
prop2: 2,
};
for (let propName in o) {
console.log(propName);
}let o = {
prop1: 1,
prop2: 2,
};
Object.keys(o).forEach((propName) => {
console.log(propName);
});let o = {
prop1: 1,
prop2: 2,
};
for (let [key, value] of Object.entries(o)) {
console.log(`${key}: ${value}`);
}let o = {
prop1: 1,
__proto__: {
prop2: 2,
},
};
for (let propName in o) {
console.log(propName);
}let o = {
prop1: 1,
__proto__: {
prop2: 2,
},
};
for (let propName in o) {
console.log(
propName,
o.hasOwnProperty(propName) ? "в объекте" : "в цепочке прототипов"
);
}let o = {
prop1: 1,
__proto__: {
prop2: 2,
},
};
for (let [key, value] of Object.entries(o)) {
console.log(`${key}: ${value}`);
}Свойства удаляются (так же как и записываются) непосредственно на объекте(на том, что до последней точки, в точечной нотации), не затрагивая цепочку прототипов.
let o = {
prop1: 1,
__proto__: {
prop1: 2,
},
};
console.log(o.prop1); // ?
delete o.prop1;
console.log(o.prop1); // ?
delete o.prop1;
console.log(o.prop1); // ?let a = { name: "Bob" };
let b = { name: "Sam" };
let settings = {};
settings[a] = { isAdmin: true };
settings[b] = { isAdmin: false };
console.log(settings[a]); // ?
console.log(settings[b]); // ?Напишите функцию, которая позволит безопасно читать свойства из объекта на любой вложенности.
Функция принимает:
- откуда свойство нужно прочитать
- путь к свойству, которое нужно прочитать
- опционально значение, которое нужно вернуть, если свойство не найдено
