diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
| commit | 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 (patch) | |
| tree | a9ef8ac1e1b8fe4207b6d64d3841bfb8990b6fd0 /files/uk/web/javascript/reference/global_objects/object/create | |
| parent | 074785cea106179cb3305637055ab0a009ca74f2 (diff) | |
| download | translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.gz translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.bz2 translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.zip | |
initial commit
Diffstat (limited to 'files/uk/web/javascript/reference/global_objects/object/create')
| -rw-r--r-- | files/uk/web/javascript/reference/global_objects/object/create/index.html | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/files/uk/web/javascript/reference/global_objects/object/create/index.html b/files/uk/web/javascript/reference/global_objects/object/create/index.html new file mode 100644 index 0000000000..189aba3ebb --- /dev/null +++ b/files/uk/web/javascript/reference/global_objects/object/create/index.html @@ -0,0 +1,406 @@ +--- +title: Object.create() +slug: Web/JavaScript/Reference/Global_Objects/Object/create +tags: + - ECMAScript 5 + - JavaScript + - 'Null' + - Object + - метод +translation_of: Web/JavaScript/Reference/Global_Objects/Object/create +--- +<div>{{JSRef}}</div> + +<p>Метод <code><strong>Object.create()</strong></code> створює новий об'єкт, використовуючи існуючий об'єкт як прототип для новоствореного об'єкта.</p> + +<div>{{EmbedInteractiveExample("pages/js/object-create.html")}}</div> + + + +<h2 id="Синтаксис">Синтаксис</h2> + +<pre class="syntaxbox">Object.create(<var>proto</var>, [<var>propertiesObject</var>])</pre> + +<h3 id="Параметри">Параметри</h3> + +<dl> + <dt><code><var>proto</var></code></dt> + <dd>Об'єкт, що має бути прототипом для новоствореного об'єкта.</dd> + <dt><code><var>propertiesObject</var></code><var> </var>{{Optional_inline}}</dt> + <dd>Якщо вказаний та не дорівнює {{jsxref("undefined")}}, об'єкт, чиї власні перелічувані властивості (тобто, властивості, визначені на самому об'єкті, а <em>не</em> перелічувані властивості, отримані через ланцюжок прототипів) визначають дескриптори властивостей, що мають бути додані до новоствореного об'єкта, з відповідними іменами властивостей. Ці властивості відповідають другому аргументу {{jsxref("Object.defineProperties()")}}.</dd> +</dl> + +<h3 id="Значення_що_повертається">Значення, що повертається</h3> + +<p>Новий об'єкт з зазначеним прототипом та властивостями.</p> + +<h3 id="Винятки">Винятки</h3> + +<p>Виняток {{jsxref("TypeError")}}, якщо параметр <code>propertiesObject</code> дорівнює {{jsxref("null")}} або це об'єкт, що не є обгорткою простого типу.</p> + +<h2 id="Приклади">Приклади</h2> + +<h3 id="Класичне_наслідування_через_Object.create">Класичне наслідування через <code>Object.create()</code></h3> + +<p>Нижче наведено приклад використання <code>Object.create()</code> для отримання класичного наслідування. Це приклад одиночного наслідування, єдиного, яке підтримує JavaScript.</p> + +<pre class="brush: js">// Shape - батьківський клас +function Shape() { + this.x = 0; + this.y = 0; +} + +// метод батьківського класу +Shape.prototype.move = function(x, y) { + this.x += x; + this.y += y; + console.info('Фігуру переміщено.'); +}; + +// Rectangle - дочірній клас +function Rectangle() { + Shape.call(this); // виклик батьківського конструктора. +} + +// дочірній клас розширює батьківській клас +Rectangle.prototype = Object.create(Shape.prototype); + +//Якщо ви не призначите Object.prototype.constructor значення Rectangle, +//він візьме prototype.constructor класу Shape (батьківського). +//Щоб уникнути цього, ми призначаємо prototype.constructor значення Rectangle (дочірній). +Rectangle.prototype.constructor = Rectangle; + +var rect = new Rectangle(); + +console.log('Чи є rect екземпляром Rectangle?', rect instanceof Rectangle); // true +console.log('Чи є rect екземпляром Shape?', rect instanceof Shape); // true +rect.move(1, 1); // Виводить 'Фігуру переміщено.' +</pre> + +<p>Якщо ви бажаєте успадкуватись від кількох об'єктів, можна використати домішки.</p> + +<pre class="brush: js">function MyClass() { + SuperClass.call(this); + OtherSuperClass.call(this); +} + +// успадкувати від одного класу +MyClass.prototype = Object.create(SuperClass.prototype); +// змішати з іншим +Object.assign(MyClass.prototype, OtherSuperClass.prototype); +// перепризначити конструктор +MyClass.prototype.constructor = MyClass; + +MyClass.prototype.myMethod = function() { + // зробити щось +}; +</pre> + +<p>Метод {{jsxref("Object.assign()")}} копіює властивості з прототипу OtherSuperClass у прототип MyClass, роблячи їх доступними для усіх екземплярів MyClass. <code>Object.assign()</code> був запроваджений у ES2015 і <a href="/uk/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Запасний_варіант_(поліфіл)">може бути відтворений поліфілом</a>. Якщо необхідна підтримка більш старих переглядачів, можна використати <code><a href="https://api.jquery.com/jQuery.extend/">jQuery.extend()</a></code> або <code><a href="https://lodash.com/docs/#assign">_.assign()</a></code>.</p> + +<h3 id="Використання_аргументу_propertiesObject_у_Object.create">Використання аргументу <code>propertiesObject</code> у <code>Object.create()</code></h3> + +<pre class="brush: js">var o; + +// створити об'єкт з прототипом null +o = Object.create(null); + + +o = {}; +// є еквівалентом: +o = Object.create(Object.prototype); + + +// У цьому прикладі ми створюємо об'єкт з парою +// зразкових властивостей. (Зауважте, що другий параметр +// встановлює ключі у відповідності до *дескрипторів властивості*.) +o = Object.create(Object.prototype, { + // foo - це звичайна властивість-значення + foo: { + writable: true, + configurable: true, + value: 'hello' + }, + // bar - це властивість-аксесор (має гетер та сетер) + bar: { + configurable: false, + get: function() { return 10; }, + set: function(value) { + console.log('Призначення `o.bar` значення', value); + } +/* з аксесорами ES2015 наш код може виглядати так + get() { return 10; }, + set(value) { + console.log('Призначення `o.bar` значення', value); + } */ + } +}); + + +function Constructor() {} +o = new Constructor(); +// є еквівалентом: +o = Object.create(Constructor.prototype); +// Звісно, якщо у функції Constructor присутній +// код ініціалізації, +// Object.create() не може його відобразити + + +// Створити новий об'єкт, чиїм прототипом є новий, порожній +// об'єкт, та додати єдину властивість 'p' зі значенням 42. +o = Object.create({}, { p: { value: 42 } }); + +// за замовчуванням властивості НЕДОСТУПНІ для запису, +// переліку чи налаштування: +o.p = 24; +o.p; +// 42 + +o.q = 12; +for (var prop in o) { + console.log(prop); +} +// 'q' + +delete o.p; +// false + +// щоб визначити властивість у ES3 +o2 = Object.create({}, { + p: { + value: 42, + writable: true, + enumerable: true, + configurable: true + } +}); +/* є еквівалентом: +o2 = Object.create({p: 42}) */ + +</pre> + +<h2 id="Користувацькі_та_нульові_обєкти">Користувацькі та нульові об'єкти</h2> + +<p>Новий об'єкт, створений на основі користувацького об'єкта (особливо об'єкт, створений на основі об'єкта <code>null</code>, який по суті є користувацьким об'єктом, що НЕ МАЄ членів), може поводитись неочікувано. Особливо під час налагодження, оскільки звичайні функції утиліт для перетворення/видалення об'єктних властивостей можуть генерувати помилки або просто втрачати інформацію (особливо якщо використовують перехоплювачі помилок, що ігнорують помилки). Наприклад, ось два об'єкти:</p> + +<pre class="brush: js">oco = Object.create( {} ); // створити нормальний об'єкт +ocn = Object.create( null ); // створити "нульовий" об'єкт + +> console.log(oco) // {} -- Виглядає нормально +> console.log(ocn) // {} -- Поки що теж виглядає нормально + +oco.p = 1; // створити просту властивість на нормальному об'єкті +ocn.p = 0; // створити просту властивість на "нульовому" об'єкті + +> console.log(oco) // {p: 1} -- Досі виглядає нормально +> console.log(ocn) // {p: 0} -- Теж виглядає нормально. АЛЕ СТРИВАЙТЕ... +</pre> + +<p><br> + Як показано вище, поки що все виглядає нормальним. Однак, при спробі використати ці об'єкти, їхні відмінності швидко стають очевидними:</p> + +<pre class="brush: js">> "oco is: " + oco // виводить "oco is: [object Object]" + +> "ocn is: " + ocn // викидає помилку: Cannot convert object to primitive value +</pre> + +<p>Перевірка лише декількох з багатьох базових вбудованих функцій більш чітко демонструє величину проблеми:</p> + +<pre class="brush: js">> alert(oco) // виводить [object Object] +> alert(ocn) // викидає помилку: Cannot convert object to primitive value + +> oco.toString() // виводить [object Object] +> ocn.toString() // викидає помилку: ocn.toString is not a function + +> oco.valueOf() // виводить {} +> ocn.valueOf() // викидає помилку: ocn.valueOf is not a function + +> oco.hasOwnProperty("p") // виводить "true" +> ocn.hasOwnProperty("p") // викидає помилку: ocn.hasOwnProperty is not a function + +> oco.constructor // виводить "Object() { [native code] }" +> ocn.constructor // виводить "undefined" +</pre> + +<p><br> + Як вже сказано, ці відмінності можуть швидко зробити процес відлагодження навіть простих на вигляд проблем дуже заплутаним. Наприклад:</p> + +<p><em>Проста звичайна функція налагодження:</em></p> + +<pre class="brush: js">// вивести пари ключ-значення властивостей верхнього рівня наданого об'єкта +function ShowProperties(obj){ + for(var prop in obj){ + console.log(prop + ": " + obj[prop] + "\n" ) + } +}</pre> + +<p><br> + <em>Не такі прості результати: (особливо якщо перехоплювач помилок сховав повідомлення про помилки)</em></p> + +<pre class="brush: js">ob={}; ob.po=oco; ob.pn=ocn; // створити складний об'єкт з наданих вище тестових об'єктів в якості значень властивостей + +> ShowProperties( ob ) // вивести властивості верхнього рівня +- po: [object Object] +- Error: Cannot convert object to primitive value + +Зауважте, що виводиться тільки перша властивість. +</pre> + +<p><br> + <em>(Але якщо такий самий об'єкт був просто створений в іншому порядку -- принаймні, в деяких реалізаціях...)</em></p> + +<pre class="brush: js">ob={}; ob.pn=ocn; ob.po=oco; // створити знову такий самий об'єкт, але створити ті самі властивості в іншому порядку + +> ShowProperties( ob ) // вивести властивості верхнього рівня +- Error: Cannot convert object to primitive value + +Зауважте, що жодна властивість не виводиться.</pre> + +<p>Зауважте, що такий відмінний порядок може виникнути статично, через відмінний зафіксований код, як ось тут, а може й динамічно, через порядок, в якому виконуються під час запуску гілки коду з додаванням властивостей, що залежить від вхідних даних та/або випадкових змінних. Знову ж таки, реальний порядок перебору не гарантований, в якому б порядку не додавалися члени об'єкта.</p> + +<h4 id="Деякі_рішення_що_не_працюють">Деякі рішення, що не працюють</h4> + +<p>Гарне вирішення проблеми відсутніх об'єктних методів не завжди є очевидним.</p> + +<p>Пряме додавання відсутнього об'єктного метода зі стандартного об'єкта НЕ працює:</p> + +<pre class="brush: js">ocn = Object.create( null ); // створити "нульовий" об'єкт (такий самий, як і раніше) + +ocn.toString = Object.toString; // оскільки йому бракує методу, призначити його прямо зі стандартного об'єкта + +<span style="letter-spacing: -0.00333rem;">> ocn.toString // виводить "toString() { [native code] }" -- схоже, що відсутній метод тепер додано</span> +> ocn.toString == Object.toString // виводить "true" -- схоже, це той самий метод, що й у стандартному об'єкті + +> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function +</pre> + +<p><br> + Пряме додавання відсутнього об'єктного метода у "прототип" нового об'єкта також не працює, оскільки у нового об'єкта немає справжнього прототипа (що й є справжньою причиною УСІХ цих проблем), і його не можна додати <strong>прямо</strong>:</p> + +<pre class="brush: js">ocn = Object.create( null ); // створити "нульовий" об'єкт (такий самий, як і раніше) + +ocn.prototype.toString = Object.toString; // Error: Cannot set property 'toString' of undefined + +ocn.prototype = {}; // спробувати створити прототип +ocn.prototype.toString = Object.toString; // оскільки об'єкту бракує методу, призначити його прямо зі стандартного об'єкта<span style="letter-spacing: -0.00333rem;"> + +> ocn.toString() // error: ocn.toString is not a function</span> +</pre> + +<p><br> + Додавання відсутнього об'єктного метода використанням стандартного об'єкта в якості прототипа нового об'єкта також не працює:</p> + +<pre class="brush: js">ocn = Object.create( null ); // створити "нульовий" об'єкт (такий самий, як і раніше) +Object.setPrototypeOf(ocn, Object); // встановити значенням прототипу нового об'єкта стандартний об'єкт + +> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function +</pre> + +<h4 id="Деякі_вдалі_рішення">Деякі вдалі рішення</h4> + +<p>Як вже сказано, пряме додавання відсутнього об'єктного методу зі <strong>стандартного об'єкта </strong>НЕ працює. Однак, пряме додавання <strong>загального</strong> метода ПРАЦЮЄ:</p> + +<pre class="brush: js">ocn = Object.create( null ); // створити "нульовий" об'єкт (такий самий, як і раніше) + +ocn.toString = toString; // оскільки об'єкту бракує методу, призначити його прямо з загальної версії + +> ocn.toString() // виводить "[object Object]" +> "ocn is: " + ocn // виводить "ocn is: [object Object]" + + +ob={}; ob.pn=ocn; ob.po=oco; // створити складний об'єкт (такий самий, як і раніше) + +> ShowProperties(ob) // вивести властивості верхнього рівня +- po: [object Object] +- pn: [object Object] +</pre> + +<p>Однак, встановлення загального <strong>прототипу</strong> прототипом нового об'єкта працює навіть краще:</p> + +<pre class="brush: js">ocn = Object.create( null ); // створити "нульовий" об'єкт (такий самий, як і раніше) +Object.setPrototypeOf(ocn, Object.prototype); // встановити значенням прототипу нового об'єкта "загальний" об'єкт (НЕ стандартний об'єкт) +</pre> + +<p><em>(На додачу до функцій, пов'язаних з рядками, що наведені вище, це також додає:)</em></p> + +<pre class="brush: js">> ocn.valueOf() // виводить {} +> ocn.hasOwnProperty("x") // виводить "false" +> ocn.constructor // виводить "Object() { [native code] }" + +// ...та вся решта властивостей та методів Object.prototype. +</pre> + +<p>Як бачимо, об'єкти, змінені таким чином, тепер виглядають дуже схожими на звичайні об'єкти.</p> + +<h2 id="Поліфіл">Поліфіл</h2> + +<p>Цей поліфіл покриває основний сценарій використання, а саме, створення нового об'єкта, для якого був обраний прототип, але не бере до уваги другий аргумент.</p> + +<p>Зауважте, що в той час як використання <code>null</code> в якості <code>[[Prototype]]</code> підтримується в реальному методі ES5 <code>Object.create</code>, цей поліфіл не може це підтримувати через обмеження, притаманне версіям ECMAScript нижче 5.</p> + +<pre class="brush: js"> if (typeof Object.create !== "function") { + Object.create = function (proto, propertiesObject) { + if (typeof proto !== 'object' && typeof proto !== 'function') { + throw new TypeError("Прототипом об'єкта може бути тільки об'єкт: " + proto); + } else if (proto === null) { + throw new Error("Реалізація Object.create у цьому браузері є шимом та не підтримує 'null' в якості першого аргументу."); + } + + if (typeof propertiesObject != 'undefined') { + throw new Error("Реалізація Object.create у цьому браузері є шимом та не підтримує другий аргумент."); + } + + function F() {} + F.prototype = proto; + + return new F(); + }; +} +</pre> + +<h2 id="Специфікації">Специфікації</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Специфікація</th> + <th scope="col">Статус</th> + <th scope="col">Коментар</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.2.3.5', 'Object.create')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Початкове визначення. Реалізоване у JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-object.create', 'Object.create')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.create', 'Object.create')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Object.create")}}</p> +</div> + +<h2 id="Див._також">Див. також</h2> + +<ul> + <li>{{jsxref("Object.defineProperty()")}}</li> + <li>{{jsxref("Object.defineProperties()")}}</li> + <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> + <li>{{jsxref("Reflect.construct()")}}</li> + <li>John Resig's post on <a href="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf()</a></li> +</ul> |
