Академический Документы
Профессиональный Документы
Культура Документы
20 февраля 2018 г.
Оглавление
1 Прототипы 2
1.1 Прототипы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Цепочки прототипов . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Способы установки прототипов . . . . . . . . . . . . . . . . . . . . 7
1.3.1 __proto__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.2 Метод create . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3.3 setPrototypeOf . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4 Эффект затенения . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5 Поля только для чтения в прототипах . . . . . . . . . . . . . . . . 10
1.6 Сеттеры и геттеры в прототипах . . . . . . . . . . . . . . . . . . . 12
1.7 Неперечисляемые поля в прототипах . . . . . . . . . . . . . . . . . 13
1
Глава 1
Прототипы
1.1. Прототипы
Сформулируем задачу: пусть у нас есть некоторый объект, который олицетво-
ряет студента. Он записан в литеральной нотации и описывает характеристи-
ки студента, а также полезные для него действия. Этот объект содержит поле
name, которое хранит имя студента и метод getName, который возвращает имя
нашего студента.
1 var student = {
2 name: 'Billy',
3 type: 'human',
4 getName: function () {
5 return this.name;
6 },
7 sleep: function () {
8 console.info('zzzZZZ...');
9 }
10 };
11
12 student.getName();
13 // Billy
2
Курс: JavaScript, часть 2: прототипы и асинхронность
дим, что в них очень много похожего: у каждого из них есть метод getName,
который выполняет одинаковую работу. Таким образом, мы дублируем реали-
зацию одного и того же метода в двух разных объектах, и это проблема.
К счастью, решение очень простое. Мы можем выделить общие части в от-
дельную конструкцию.
Назовем объединяющий объект person/личность. В итоге мы получим три
несвязанных объекта: студента, преподавателя и личность.
1 var person = {
2 type: 'human',
3 getName: function () {
4 return this.name;
5 }
6 };
1 var student = {
2 name: 'Billy',
3 };
4 var person = {
5 getName: function () {
6 return this.name;
7 }
8 };
9 person.getName.call(student);
3
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 name: 'Billy',
3 sleep: function () {},
4 [[Prototype]]: <link to person>,
5 };
6 student['[[Prototype]]'] = person; //так не работает!
4
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 name: 'Billy',
3 [[Prototype]]: <person>
4 };
5 var person = {
6 type: 'human',
7 getName: function () {
8 return this.name;
9 }
10 };
1 var student = {
2 name: 'Billy',
3 [[Prototype]]: <person>
4 };
5 var person = {
6 type: 'human',
7 [[Prototype]]: <Object.prototype>
8 };
5
Курс: JavaScript, часть 2: прототипы и асинхронность
для всех объектов. И уже там наш поиск остановится, так как внутреннее поле
Prototype глобального прототипа для всех объектов имеет значение null.
Помимо общего, глобального прототипа для всех объектов, существуют в язы-
ке более частные глобальные прототипы: для массивов, функций, и т.д. Каж-
дый из этих прототипов по умолчанию в качестве прототипа имеет глобальный
прототип для всех объектов. И для того, чтобы поиск метода или поля по це-
почке прототипа всегда заканчивался, в этом глобальном прототипе в поле
Prototype, во внутреннем поле, хранится значение null.
6
Курс: JavaScript, часть 2: прототипы и асинхронность
4 lecturer.__proto__ =
,→ student;
5 student.__proto__ =
,→ lecturer;
6
7 console.info(lecturer.abrakadabra);
1.3.1. __proto__
Первый — это сеттер, геттер __proto__. Не идеальный метод:
Особенности способа:
7
Курс: JavaScript, часть 2: прототипы и асинхронность
1.3.3. setPrototypeOf
Последний способ установки прототипа – специальный метод setPrototypeOf.
Этот метод принимает уже два параметра: первый — исходный объект, а вто-
рой — объект, который мы хотим видеть в качестве прототипа для исходного.
1 var student = {
2 name: 'Billy',
3 sleep: function () {}
4 };
5
6 var person = {
7 type: 'human',
8 getName: function () {}
9 };
10
11 Object.setPrototypeOf(student, person);
12
13 student.getName();
14 // Billy
Особенности способа:
8
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 name: 'Billy',
3 [[Prototype]]: <person>
4 }
5
6 var person = {
7 type: 'human',
8 getName: function () {}
9 }
10
11 console.info(student.type); // human
12
13 student.type = 'robot';
14
15 console.info(student.type); // robot
16
17 console.info(person.type); // ???
9
Курс: JavaScript, часть 2: прототипы и асинхронность
1 console.info(person.type); // 'human'
1 Object.prototype = {
2 toString: function () {}
3 };
4 student.toString();
5 // [object Object]
6 console.info('Hello,' + student);
7 // Hello, [object Object]
10
Курс: JavaScript, часть 2: прототипы и асинхронность
1 'use strict';
2 var student = { name: 'Billy' };
3 Object.defineProperty(student,
4 'gender'
5 , {
6 writable: false,
7 value: 'male'
8 });
1 Object.defineProperty(person,
2 'planet', {
3 writable: false,
4 value: 'Earth'
5 });
6
7 console.info(student.planet); // Earth
8
11
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 name: 'Billy',
3 [[Prototype]]: <person>
4 };
5
6 Object.defineProperty(student,'age', {
7 set: function(age) { this._age = parseInt(age); },
8 get: function() { return this._age; }
9 });
10
13 console.info(student.age); // 20;
12
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 [[Prototype]]: <person>
3 };
4 var person = {
5 type: 'human'
6 };
7 Object.defineProperty(person,'age', {
8 set: function(age) { this._age = parseInt(age); },
9 get: function() { return this._age; }
10 });
11
14 console.info(student.age); // 20;
15
16 student.hasOwnProperty(age); // false;
13
Курс: JavaScript, часть 2: прототипы и асинхронность
14 // 'age', 'name'
12 console.info(keys);
13
14 // ['name']
14
Курс: JavaScript, часть 2: прототипы и асинхронность
3 Object.defineProperty(student,'age', {
4 enumerable: false,
5 value: '20'
6 });
7
11 Object.keys(student);
12 // ['name']
15
Курс: JavaScript, часть 2: прототипы и асинхронность
1 var student = {
2 name: 'Billy',
3 [[Prototype]]: <person>
4 };
5
6 var person = {
7 type: 'human'
8 };
9
10 Object.defineProperty(person,'age', {
11 enumerable: false
12 });
13
Важно заметить, что у глобальных прототипов для объектов или для массивов
поля, обозначенные там, неперечисляемые. Мы не увидим их в попытке пере-
числить все поля конкретного объекта, несмотря на то, что в его прототипе
может лежать глобальный прототип.
1 Object.prototype = {
2 toString: function () {},
3 [[Prototype]]: null
4 };
5 var person = {
6 type: 'human',
7 [[Prototype]]: <Object.prototype>
8 };
9
12 // 'type'
16