为啥我们在 Javascript 中使用术语阴影而不是覆盖?

Posted

技术标签:

【中文标题】为啥我们在 Javascript 中使用术语阴影而不是覆盖?【英文标题】:Why do we use the term shadow instead of override in Javascript?为什么我们在 Javascript 中使用术语阴影而不是覆盖? 【发布时间】:2021-05-06 03:47:08 【问题描述】:

我想我在开始之前就知道了这个问题的答案,但是在 Google 上按照这些思路进行了多次搜索之后,我找不到明确的答案。

这个问题假设我们在 Ecmascript 6 及更高版本中使用类模式。

我最初的信念是方法覆盖

在面向对象的编程中,是一种语言特性,它允许 子类或子类来提供一个特定的实现 已经由其超类或父类之一提供的方法 类。 Wikipedia

另一方面,方法阴影(不仅仅是块范围'变量阴影'-Wikipedia)似乎只在像 C# 这样的强类型语言的上下文中才有意义,它允许您设置一个 ' 的实例子类”作为“基类”类型,这意味着实例恢复为基类方法,而不是任何“阴影”方法。

public abstract class BaseClass

    public virtual void shadowedMethod()
    
        Console.WriteLine("This is the BaseClass version");
    

public class DerivedClass : BaseClass

    public new void shadowedMethod()
    
        Console.WriteLine("This is the Derived child class");
    

public class Program

    public static void Main()
    
        BaseClass instance = new DerivedClass(); // Because BaseClass type is set instead of DerivedClass
        instance.shadowedMethod(); // It prints "This is the BaseClass version"
    

Code adapted from this article

所以问题是:为什么大多数 JS 线程和文档ECMA Standard 交替使用覆盖和阴影(但倾向于使用阴影)?我们不应该只用一个词来停止混淆吗?在 javascript 中,重写和隐藏方法之间实际上存在细微差别吗?

【问题讨论】:

ECMAScript 标准仅在 OOP 上下文中使用“覆盖”,而“遮蔽”仅用于范围绑定。它们不能互换使用。 啊,我可能需要花更多时间阅读标准。我的陈述更多地基于 Zakas 的“理解 ECMASCRIPT 6”,他说“派生类上的方法总是隐藏基类上的同名方法” 【参考方案1】:

我很难在 Javascript 的上下文中找到明确的定义。所以这是我回答自己问题的最佳尝试。

看起来派生类(作为基类)中具有相同名称的所有方法都是“影子方法”,并且接受相同参数(因此创建相同接口)的方法子集也是“被覆盖的方法,因为“被覆盖的成员必须接受相同的数据类型和参数数量”。 (see this article)

如果派生类上的方法使用相同的签名(接受相同的参数),则它会覆盖父/基类:

class BaseClass 
  overriddenMethod(a) 
    return a;
  


class DerivedClass 
  overriddenMethod(a) 
    return 2*a;
  

但如果派生类方法接受不同的参数,它只是'遮蔽':

class BaseClass 
  overriddenMethod(a) 
    return a;
  


class DerivedClass 
  overriddenMethod(a, b)  // This is not overriding because it accepts different parameters.
    return a + b;
  

更详细地说,它是“阴影”的,因为 Javascript 是一种原型语言,这意味着一切都是对象(甚至是类定义),因此一切最终都是对象上的变量,因此是“变量阴影”上的变量outerscope 在原型链的上游。

【讨论】:

对象上的“Shadowing”通常指的是 properties,而不仅仅是方法。如果您有两个名称相同但值不同的属性,则拥有的属性 shadows 继承的属性。该术语还意味着您不能再从对象访问继承的属性 - obj.prop 总是会引用自己的属性。

以上是关于为啥我们在 Javascript 中使用术语阴影而不是覆盖?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 JavaScript 对象中使用公共方法? [复制]

为啥过滤器(阴影)导致我的 SVG 在 Safari 中消失?

为啥在字符串中使用 javascript 转义字符的引号需要是 \\' 而不是 \'

3dmax为啥没有阴影

为啥要设计一个库来在 Javascript 中使用 const [] 而不是 const ?

为啥我可以在javascript中删除一个声明为a = 1的变量而不是一个声明的var b = 1 [重复]