Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我能决定调用一个不存在的对象方法时会发生什么吗?_Javascript - Fatal编程技术网

Javascript 我能决定调用一个不存在的对象方法时会发生什么吗?

Javascript 我能决定调用一个不存在的对象方法时会发生什么吗?,javascript,Javascript,我有如下代码: obj.foo(); // obj might, or might not have a `foo` method. 我想知道我是否可以覆盖在我的代码中调用obj.foo时发生的情况,例如: obj.foo = function(){ alert ("Hello"); }); obj.onCallNonExistentMethod = function(){ // I know this is imaginary syntax alert("World"); } obj

我有如下代码:

obj.foo(); // obj might, or might not have a `foo` method.
我想知道我是否可以覆盖在我的代码中调用
obj.foo
时发生的情况,例如:

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\u missing
const\u missing
或类似的东西

我可以重写JavaScript中调用不存在的对象方法时发生的事情吗?如果可以,我该怎么做


我们的目标是验证我提供给用户的API,以便他们可以安全地使用API,并且我可以更清楚地警告他们错误。

不幸的是,这在任何广泛支持的方式下都是不可能的。最接近的方法是对所有调用使用代理函数,也就是说,不要使用
foo.bar()
而是使用类似
foo.invoke('bar')
。然而,这很难看,很可能接近你在第一部分“不感兴趣”中的意思

在松散类型的语言中,期望开发人员传递兼容的对象是很常见的,也就是说,在传递意外的对象时出错通常是可以的



然而,如果您足够幸运地使用支持ECMAScript和谐特性的JS引擎(显然IE不支持),您可以使用来实现这一点。基本上,您可以将对象包装在代理中,这样就可以捕获对象,例如迭代对象、检索属性,甚至创建属性。除了这两个链接之外,还值得一试。

如果您使用的是严格定义的对象,您应该使用自定义对象而不是对象文字:

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();
然后,您可以使用
instanceof
操作符来判断对象是否为
Foo
实例:

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

这在今天并不是很有用(因为浏览器支持不稳定),但将允许您编写代码来拦截对对象的属性访问。换句话说,当你写作时:

obj.foo();

代理的陷阱可以返回它想要的(被调用的)任何内容,而不管原始对象上是否存在属性。

两年前,Benjamin,你对行为类型的概念不是很了解,是吗

幸运的是,在写了这个问题之后,您很快就会意识到这一点,即使是在JavaScript中,这也解决了您在这里提到的确切问题,只是从来没有使用过它

所以,要回答你的问题:

  • 是的,这是完全可能做到的
  • 你可能不应该为你所提供的情况负责
怎么做 如果您只需要通过支持真正(真正)的新浏览器,那么这是完全可行的

因此,虽然浏览器支持非常不稳定,但

为什么你不应该 接口传递行为,上述情况如打字错误,通常可以(也应该)被jshint或ternjs等静态分析工具捕获


检查拼写错误的工具根本不足以在JavaScript中传达行为,类型检查通常被认为是一种反模式——在JavaScript、Ruby和Python等语言中,您知道将获得的类型。

您的问题标题具有误导性。我希望有人能做一些像
var undefined=@ThiefMaster,这是完全合法的,因为这不是他想要的。除此之外,现代JavaScript引擎阻止您重新定义全局
未定义的
。感谢您的回答,但我明确表示我希望避免构造函数模式。我想做的是保存“hasFunction”的额外样板文件。如果您可以保证参数是函数或不存在,您可以使用
foo.bar&&foo.bar()
作为简写,这在功能上与
if(foo.bar){foo.bar()}
相同。这太棒了!遗憾的是,正如您所说,浏览器支持非常不稳定:/
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