--- title: Object.prototype.__noSuchMethod__ slug: Web/JavaScript/Reference/Global_Objects/Object/noSuchMethod tags: - JavaScript - Non-standard - Object - Property - Prototype - Reference translation_of: Archive/Web/JavaScript/Object.noSuchMethod ---
{{JSRef("Global_Objects", "Object")}} {{non-standard_header}}
Хотя свойство __noSuchMethod__ и нестандартно, спецификация ECMAScript Harmony (ES6) содержит объект {{jsxref("Proxy")}}, с помощью которого вы можете сделать всё тоже самое, что и при использовании этого свойством (и даже больше).

Сводка

Свойство __noSuchMethod__ ссылается на функцию, выполняющуюся каждый раз при вызове на объекте несуществующего метода.

Синтаксис

obj.__noSuchMethod__ = fun

Параметры

fun
Функция, имеющая вид
function(id, args) { . . . }
id
Имя вызванного несуществующего метода
args
Массив аргументов, переданный в метод

Описание

По умолчанию, при попытке вызвать не существующий в объекте метод, будет выброшено исключение {{jsxref("Global_Objects/TypeError", "TypeError")}}. Это поведение можно обойти, определив функцию __noSuchMethod__ в качестве члена объекта. Функция принимает два аргумента, первый является именем метода, который попытались вызвать, а второй — массивом аргументов, которые были переданы в метод при его вызове. Второй аргумент является настойщим массивом (то есть, он наследуется через цепочку прототипов от {{jsxref("Array.prototype")}}), а не массивоподобным объектом arguments.

Если данный метод не может быть вызван, либо по причине того, что он установлен в {{jsxref("Global_Objects/undefined", "undefined")}} по умолчанию, либо удалён, либо вручную установлен в не-функцию, движок JavaScript вернётся к выбрасыванию исключения {{jsxref("Global_Objects/TypeError", "TypeError")}}.

Примеры

Пример: простая проверка свойства __noSuchMethod__

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 ()

Пример: использование свойства __noSuchMethod__ для симуляции множественного наследования

Ниже показан пример кода, реализующего примитивную форму множественного наследования.

// Не работает с множественным наследованием объектов в качестве родителей
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);
}

Ниже показан пример использования этой идеи.

// Пример первого базового класса

function NamedThing(name) {
    this.name = name;
}

NamedThing.prototype = {
    getName: function() { return this.name; },
    setName: function(newName) { this.name = newName; }
}

// Пример второго базового класса

function AgedThing(age){
    this.age = age;
}

AgedThing.prototype = {
    getAge: function() { return this.age; },
    setAge: function(age) { this.age = age; }
}

// Дочерний класс. Наследуется от NamedThing и AgedThing, а также определяет свойство address

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) ? 'в' : 'не в') + ' объекте bob');
console.log('возраст Боба: ' + bob.getAge());
console.log('getName лежит ' + (('getName' in bob) ? 'в' : 'не в') + ' объекте bob');
console.log('имя Боба: ' + bob.getName());
console.log('getAddr лежит ' + (('getAddr' in bob) ? 'в' : 'не в') + ' объекте bob');
console.log('адрес Боба: ' + bob.getAddr());

Вывод примера будет следующим:

getAge лежит не в объекте bob
возраст Боба: 25
getName лежит не в объекте bob
имя Боба: Боб
getAddr лежит в объекте bob
адрес Боба: Нью-Йорк

Спецификации

Не является частью какой-либо спецификации.

Совместимость с браузерами

{{CompatibilityTable}}
Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка {{CompatNo}} {{CompatGeckoDesktop("1.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}
Возможность Android Chrome для Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка {{CompatNo}} {{CompatNo}} {{CompatGeckoMobile("1.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}