有没有办法捕获尝试访问不存在的属性或方法?

Tor*_*amo 18 javascript

例如这段代码:

function stuff() {
  this.onlyMethod = function () {
    return something;
  }
}

// some error is thrown
stuff().nonExistant();
Run Code Online (Sandbox Code Playgroud)

有没有办法做PHP之类的东西__call作为对象内部的后备?

function stuff() {
  this.onlyMethod = function () {
    return something;
  }
  // "catcher" function
  this.__call__ = function (name, params) {
    alert(name + " can't be called.");
  }
}

// would then raise the alert "nonExistant can't be called".
stuff().nonExistant();
Run Code Online (Sandbox Code Playgroud)

也许我会再解释一下我在做什么.

该对象包含另一个对象,该对象具有应该可以通过此对象直接访问的方法.但是这些方法对于每个对象都是不同的,所以我不能只是路由它们,我需要能够动态地调用它们.

我知道我可以让它里面的对象成为主对象的属性stuff.obj.existant(),但我只是想知道我是否可以避免它,因为主要对象是一种包装器,只是暂时添加一些功能(并使它更容易同时访问对象).

Nic*_* NZ 14

嗯,似乎和谐(ES6),会有一种方式,与其他编程语言相比,它更复杂.基本上,它涉及使用Proxy内置对象在对象上创建包装器,并修改其在其上实现的默认行为的方式:

obj  = new Proxy({}, 
        { get : function(target, prop) 
            { 
                if(target[prop] === undefined) 
                    return function()  {
                        console.log('an otherwise undefined function!!');
                    };
                else 
                    return target[prop];
            }
        });
obj.f()        ///'an otherwise undefined function!!'
obj.l = function() {console.log(45);};
obj.l();       ///45
Run Code Online (Sandbox Code Playgroud)

代理将所有未由处理程序处理的方法转发到普通对象中.所以它就好像它不在那里,从代理你可以修改目标.还有更多的处理程序,甚至一些修改原型获取,以及任何属性访问的设置者是!

正如您想象的那样,目前并非所有浏览器都支持此功能,但在Firefox中您可以非常轻松地使用Proxy界面,只需转到MDN文档即可

如果设法在这上面添加一些语法糖会让我更开心,但无论如何,以一种已经很强大的语言拥有这种力量是很好的.祝你今天愉快!:)

PD:我没有复制rosettacode js条目,我更新了它.


Anu*_*rag 10

有一种方法可以为不存在的方法调用通用处理程序,但它是非标准的.查看Firefox 的noSuchMethod.将允许您动态地将调用路由到未定义的方法.似乎v8也得到了它的支持.

要使用它,请在任何对象上定义此方法:

var a = {};

a.__noSuchMethod__ = function(name, args) {
    console.log("method %s does not exist", name);
};

a.doSomething(); // logs "method doSomething does not exist"
Run Code Online (Sandbox Code Playgroud)

但是,如果你想要一个跨浏览器的方法,那么简单的try-catch阻塞如果要走的路:

try {
    a.doSomething();
}
catch(e) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

如果您不想在整个代码中编写try-catch,那么您可以向主对象添加一个包装器,通过该主对象路由所有函数调用.

function main() {
    this.call = function(name, args) {
        if(this[name] && typeof this[name] == 'function') {
            this[name].call(args);
        }
        else {
            // handle non-existant method
        }
    },
    this.a = function() {
        alert("a");
    }
}

var object = new main();
object.call('a') // alerts "a"
object.call('garbage') // goes into error-handling code
Run Code Online (Sandbox Code Playgroud)