Skip to content

Latest commit

 

History

History
535 lines (372 loc) · 10 KB

File metadata and controls

535 lines (372 loc) · 10 KB
title Занятие 6
description Объектная модель в Javascript. Прототипное наследование

OTUS

Javascript Basic

Вопросы?

Объектная модель в 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()); //?

__proto__

При обращении к свойству объекта:

  • свойство ищется в самом объекте
  • если свойство не найдено, делается поиск в прототипе объекта
  • если свойство не найдено в прототипе, делается поиск дальше по цепочке прототипов, пока цепочка не закончится
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); // ?

Задание прототипа:

Вопросы?

Итерация по полям объекта

  • 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]); // ?

Практика

Напишите функцию, которая позволит безопасно читать свойства из объекта на любой вложенности.

Функция принимает:

  • откуда свойство нужно прочитать
  • путь к свойству, которое нужно прочитать
  • опционально значение, которое нужно вернуть, если свойство не найдено

Дополнительные материалы

Вопросы?

Опрос