我在学how to make OOP with JavaScript.它有接口概念吗(比如Java的interface)?

所以我可以创造一个听众...

推荐答案

没有"该类必须具有这些函数"的概念(即本身没有接口),因为:

  1. JavaScript继承基于对象,而不是类.在你意识到之前,这不是什么大事:
  2. JavaScript是一种extremely动态类型的语言--您可以使用适当的方法创建对象,这将使其符合接口and then undefine all the stuff that made it conform.颠覆类型系统非常容易--甚至是意外的!--一开始就不值得try 创建类型系统.

相反,JavaScript使用的是所谓的duck typing.(如果它像鸭子一样走路,像鸭子一样呱呱叫,就JS而言,它就是鸭子.)如果您的对象有quack()、walk()和fly()方法,那么代码可以在任何它希望对象能够行走、呱呱和飞行的地方使用它,而不需要实现一些"可回避"的接口.接口正是代码使用的函数集(以及这些函数的返回值),通过duck输入,您可以免费获得这些函数.

这并不是说,如果你try 调用some_dog.quack(),你的代码不会中途失败;你会得到一个打字错误.坦率地说,如果你让狗嘎嘎叫,你会遇到更大的问题;可以说,当你把所有的鸭子排成一行,不让狗和鸭子混在一起,除非你把它们当作普通动物对待时,鸭子打字效果最好.换句话说,即使界面是流动的,它仍然存在;把一只狗交给一开始就希望它呱呱叫、飞起来的代码,这通常是一个错误.

但是,如果您确定您做的是正确的事情,那么您可以在try 使用某个特定方法之前,通过测试是否存在该方法来绕过嘎嘎狗问题.像这样的东西

if (typeof(someObject.quack) == "function")
{
    // This thing can quack
}

所以你可以在使用之前判断所有可以使用的方法.不过,语法有点难看.有一种稍微漂亮一点的方式:

Object.prototype.can = function(methodName)
{
     return ((typeof this[methodName]) == "function");
};

if (someObject.can("quack"))
{
    someObject.quack();
}

这是标准的JavaScript,所以它应该可以在任何值得使用的JS解释器中工作.它还有一个额外的好处,就是像英语一样阅读.

对于现代浏览器(即除IE 6-8之外的几乎所有浏览器),甚至有一种方法可以防止属性出现在for...in中:

Object.defineProperty(Object.prototype, 'can', {
    enumerable: false,
    value: function(method) {
        return (typeof this[method] === 'function');
    }
}

问题是IE7对象根本没有.defineProperty,而且在IE8中,据称它只在宿主对象(即DOM元素等)上工作.如果兼容性有问题,您不能使用.defineProperty.(我甚至不会提到IE6,因为它在中国以外已经相当无关紧要了.)

另一个问题是,一些编码风格喜欢假设每个人都写不好的代码,并禁止修改Object.prototype,以防有人想要盲目使用for...in.如果您关心这一点,或者正在使用(IMO broken)代码,请try 稍微不同的版本:

function can(obj, methodName)
{
     return ((typeof obj[methodName]) == "function");
}

if (can(someObject, "quack"))
{
    someObject.quack();
}

Javascript相关问答推荐

使用axios.获取实时服务器时的404响应

从PWA中的内部存储读取文件

fs. writeFile()vs fs.writeFile()vs fs.appendFile()

react/redux中的formData在expressjs中返回未定义的req.params.id

从mat—country—select获取整个Country数组

我不知道为什么setwritten包装promise 不能像我预期的那样工作

函数返回与输入对象具有相同键的对象

我的服务工作器没有连接到我的Chrome扩展中的内容脚本.我该怎么解决这个问题?

我在Django中的视图中遇到多值键错误

如何修复我的数据表,以使stateSave正常工作?

禁用.js文件扩展名并从目录导入隐式根index.js时,找不到NodeJS导入模块

从页面到应用程序(NextJS):REST.STATUS不是一个函数

同一类的所有div';S的模式窗口

Reaction组件在本应被设置隐藏时仍显示

基于产品ID更新条带产品图像的JavaScript命中错误

react -原生向量-图标笔划宽度

我不知道如何纠正这一点.

如何在每隔2分钟刷新OKTA令牌后停止页面刷新

将延迟加载的模块转换为Eager 加载的模块

如何在不将整个文件加载到内存的情况下,在Node.js中实现Unix粘贴命令?