1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
---
title: Object.prototype.__noSuchMethod__
slug: Web/JavaScript/Reference/Global_Objects/Object/noSuchMethod
tags:
- JavaScript
- Object
- Властивість
- застаріла
- нестандартна
translation_of: Archive/Web/JavaScript/Object.noSuchMethod
---
<div>{{JSRef}}{{Non-standard_Header}}{{Obsolete_Header("gecko43")}}</div>
<p>Властивість <strong><code>__noSuchMethod__</code></strong> використовувалась для посилання на функцію, що мала виконатися, коли на об'єкті викликався неіснуючий метод, але ця функція більше не доступна.</p>
<p>В той час як метод <code><strong>__noSuchMethod__</strong></code> був прибраний, специфікація ECMAScript 2015 містить об'єкт {{JSxRef("Proxy")}}, який допоможе досягти описаного нижче (і навіть більше).</p>
<h2 id="Синтаксис">Синтаксис</h2>
<pre class="syntaxbox"><code><var>obj</var>.__noSuchMethod__ = <var>fun</var></code></pre>
<h3 id="Параметри">Параметри</h3>
<dl>
<dt><code>fun</code></dt>
<dd>Функція, що має вигляд</dd>
<dd>
<pre class="brush: js"><code>function (<var>id</var>, <var>args</var>) { . . . }</code></pre>
<dl>
<dt><code>id</code></dt>
<dd>Ім'я неіснуючого методу, що був викликаний</dd>
<dt><code>args</code></dt>
<dd>Масив аргументів, переданих у метод</dd>
</dl>
</dd>
</dl>
<h2 id="Опис">Опис</h2>
<p>За замовчуванням спроба викликати метод, який не існує, на об'єкті призводить до викидання {{JSxRef("TypeError")}}. Цю поведінку можна обійти, визначивши функцію у властивості об'єкта <code>__noSuchMethod__</code>. Функція приймає два аргумента, перший - це ім'я метода, що викликається, другий - це масив аргументів, які передаються під час виклику. Другий аргумент є справжнім масивом (тобто, він успадковується через ланцюг {{JSxRef("Array.prototype")}}), а не подібним до масиву <a href="/uk/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments" title="JavaScript/Reference/Functions/arguments">об'єктом arguments</a>.</p>
<p>Якщо цей метод не можна викликати, чи тому що він дорівнює <code>undefined</code>, чи був видалений, чи йому вручну було присвоєне нефункціональне значення, рушій JavaScript повернеться до викидання <code>TypeError</code>.</p>
<h2 id="Приклади">Приклади</h2>
<h3 id="Проста_перевірка___noSuchMethod__">Проста перевірка <code>__noSuchMethod__</code></h3>
<pre class="brush: js">var o = {
__noSuchMethod__: function(id, args) {
console.log(id, '(' + args.join(', ') + ')');
}
};
o.foo(1, 2, 3);
o.bar(4, 5);
o.baz();
// Виведе
// foo (1, 2, 3)
// bar (4, 5)
// baz ()
</pre>
<h3 id="Використання___noSuchMethod___для_імітації_множинного_спадкування">Використання <code>__noSuchMethod__</code> для імітації множинного спадкування</h3>
<p>Приклад коду, що реалізує примітивну форму множинного спадкування, наведений нижче.</p>
<pre class="brush: js">// Не працює, якщо батьківські об'єкти є результатом множинного спадкування
function noMethod(name, args) {
var parents = this.__parents_;
// Пройти через усі батьківські об'єкти
for (var i = 0; i < parents.length; i++) {
// Якщо знаходимо функцію у батьківського об'єкта, викликаємо її
if (typeof parents[i][name] == 'function') {
return parents[i][name].apply(this, args);
}
}
// Якщо ми дістались сюди, метод не був знайдений
throw new TypeError;
}
// Додавало батьківський об'єкт для множинного спадкування
function addParent(obj, parent) {
// Якщо об'єкт неініціалізований, ініціалізуємо його
if (!obj.__parents_) {
obj.__parents_ = [];
obj.__noSuchMethod__ = noMethod;
}
// Додати батьківський об'єкт
obj.__parents_.push(parent);
}
</pre>
<p>Приклад використання цієї ідеї наведений нижче.</p>
<pre class="brush: js">// Базовий клас 1
function NamedThing(name) {
this.name = name;
}
NamedThing.prototype = {
getName: function() { return this.name; },
setName: function(newName) { this.name = newName; }
}
// Базовий клас 2
function AgedThing(age) {
this.age = age;
}
AgedThing.prototype = {
getAge: function() { return this.age; },
setAge: function(age) { this.age = age; }
}
// Дочірній клас. Наслідується від NamedThing та AgedThing,
// а також визначає адресу
function Person(name, age, address){
addParent(this, NamedThing.prototype);
NamedThing.call(this, name);
addParent(this, AgedThing.prototype);
AgedThing.call(this, age);
this.address = address;
}
Person.prototype = {
getAddr: function() { return this.address; },
setAddr: function(addr) { this.address = addr; }
}
var bob = new Person('Боб', 25, 'Нью-Йорк');
console.log('getAge ' + (('getAge' in bob) ? 'належить' : 'не належить') + ' Бобу');
// getAge не належить Бобу
console.log("Вік Боба: " + bob.getAge());
// Вік Боба: 25
console.log('getName ' + (('getName' in bob) ? 'належить' : 'не належить') + ' Бобу');
// getName не належить Бобу
console.log("Ім'я Боба: " + bob.getName());
// Ім'я Боба: Боб
console.log('getAddr ' + (('getAddr' in bob) ? 'належить' : 'не належить') + ' Бобу');
// getAddr належить Бобу
console.log("Адреса Боба: " + bob.getAddr());
// Адреса Боба: Нью-Йорк
</pre>
<h2 id="Специфікації">Специфікації</h2>
<p>Не є частиною жодних специфікацій. Ця функціональність була прибрана, дивіться {{bug(683218)}}.</p>
<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2>
<div>
<p>{{Compat("javascript.builtins.Object.noSuchMethod")}}</p>
</div>
|