Могу ли я решить, что происходит при вызове метода несуществующих объектов?

У меня есть код, который выглядит так:

obj.foo(); // obj might, or might not have a `foo` method. 

Я хочу знать, могу ли я переопределить то, что происходит, когда obj.foo вызывается в моем коде, например:

  • Как добавить / создать / создать текстовый узел с помощью jQuery
  • Как рассчитать значение y для данного x, используя d3.js
  • Backbone.js и pushState
  • Ng-repeat с ng-transclude внутри директивы
  • Может ли javascript, работающий внутри iframe, влиять на главную страницу?
  • Как сделать итератор из класса ES6
  •  obj.foo = function(){ alert ("Hello"); }); obj.onCallNonExistentMethod = function(){ // I know this is imaginary syntax alert("World"); } obj.foo(); // alerts "Hello" delete obj.foo; obj.foo(); // alerts "World" , would TypeError without the method missing handler. 

    Из того, что я понимаю, в Ruby это будет method_missing или const_missing или что-то подобное.

    Могу ли я переопределить, что происходит при вызове несуществующего метода объекта в JavaScript? Если смогу, как мне это сделать?

    Целью является проверка API, который я предоставляю пользователям, чтобы они могли безопасно использовать API, и я могу более четко их предупредить об ошибках.

    4 Solutions collect form web for “Могу ли я решить, что происходит при вызове метода несуществующих объектов?”

    К сожалению, это невозможно в любом широко распространенном виде. Самое близкое, что вы можете получить, это использовать прокси-функцию для всех вызовов, т. foo.invoke('bar') Вместо foo.bar() вы будете использовать что-то вроде foo.invoke('bar') . Однако это довольно уродливо и, скорее всего, близко к тому, что вы имели в виду в первой части «не заинтересованы».

    В свободно типизированных языках довольно часто можно ожидать, что разработчик передаст совместимые объекты, т. Е. Получить сообщение об ошибке при передаче чего-то неожиданного.


    Однако, если вам посчастливилось использовать движок JS, который поддерживает функции ECMAScript-гармонии (очевидно, IE не работает), вы можете использовать объекты прокси для достижения этого. В основном вы переносите свой объект в прокси-сервер, который позволяет захватывать большинство операций над объектом, таких как итерация, извлечение свойства или даже создание свойств. Кроме того, две ссылки, рассматривающие этот ответ на этот вопрос, могут быть полезны.

    Два года назад Бенджамин, ты не очень хорошо понимал понятие поведенческой типизации?

    К счастью для вас, вы скоро поймете, что интерфейс не является структурным в JavaScript с момента написания этого вопроса и даже написал библиотеку, которая решает точный вопрос, о котором вы говорите, но никогда не использовать его.

    Итак, чтобы ответить на ваш вопрос:

    • Да, это вполне возможно.
    • Вы, вероятно, не должны это делать.

    Как это сделать

    Это прекрасно, если вам нужно только реально поддерживать действительно (действительно реально) новые браузеры через Proxy API .

     var realObject = { foo: function(){ alert("Bar"); }); // our fooable api var api = new Proxy({}, { get: function(target, name){ if(name in target){ // normal API call return target[name]; } // return whatever you want instead of the method: return function(){ alert("Baz"); }); } }); api.foo(); //alerts Bar api.bar(); //alerts Baz api.IWillNotBuyThisRecordItIsScratched(); // alerts Baz 

    Таким образом, хотя поддержка браузера очень трясается,

    Почему вы не должны

    Интерфейсы передают поведение, выше таких случаев, как опечатки, которые могут (и должны) быть обычно пойманы статическими инструментами анализа, такими как jshint или ternjs.

    Проверка инструментов для опечаток просто недостаточно мощна, чтобы передать поведение в JavaScript, проверка типов считается анти-шаблоном, как правило – на таких языках, как JavaScript, Ruby и Python, вы знаете типы, которые вы получите.

    Если вы работаете со строго определенными объектами, вы должны использовать пользовательские объекты вместо объектных литералов:

     function Foo(bar, baz) { this.bar = bar; this.baz = baz; } Foo.prototype = { fizz: function () { alert(this.bar + ' ' + this.baz + '!'); } }; //elsewhere f = new Foo('Hello', 'World'); f.fizz(); в function Foo(bar, baz) { this.bar = bar; this.baz = baz; } Foo.prototype = { fizz: function () { alert(this.bar + ' ' + this.baz + '!'); } }; //elsewhere f = new Foo('Hello', 'World'); f.fizz(); 

    И затем вы можете определить, является ли объект экземпляром Foo , используя оператор instanceof :

     function Buzz(foo) { if (foo instanceof Foo) { foo.fizz(); } } f = new Foo('Hello', 'World'); Buzz(f); 

    Если вы просто хотите проверить, содержит ли объект функцию по определенному параметру, вы можете использовать что-то вроде:

     function hasFunction(obj, param) { return (typeof obj[param] === 'function'); } o = { foo: function () {} } hasFunction(o, 'foo'); //true hasFunction(o, 'bar'); //false 

    Сегодня это не очень полезно (благодаря поддержке пятнистого браузера), но Proxy API позволит вам писать код, который перехватывает доступ к объектам на объекте. Другими словами, когда вы пишете:

     obj.foo(); 

    Ловушка прокси-сервера может затем вернуть все, что захочет (для вызова), независимо от того, действительно ли свойство существует на исходном объекте.

    JavaScript делает сайт умным, красочным и простым использованием.