【问题标题】:How to protect functions which are called with different contexts from breaking?如何保护在不同上下文中调用的函数不被破坏?
【发布时间】:2023-03-15 02:10:01
【问题描述】:

我对 javascript 还很陌生,现在我了解了如何使用上下文调用函数。

这是一个在我脑海中提出问题的简单示例。假设我们有这个例子:

var myObj = {
    bar: function() {
      console.log("Lets got to the bar!");
    }
}

/* how can this be protected from errors, 
 * if a passed object doesn't contain bar */
function foo()
{
   this.bar();
} 

foo.call(myObj);

现在,如何保护 foo 不被破坏?在某些 OOP 语言(比如说 Java)中,这可以通过接口来实现。所以在那种情况下,如果被实例化的对象没有实现接口方法,编译器会通过一个错误来保护代码/程序不出错(当然是在这种情况下)。

public interface MyInterface
{
   public void bar();
}

public class MyClass implements MyInterface
{
   public void bar()
   {
     System.println("Lets go to the bar");
   }
}

MyInterface m = new MyClass();
m.bar(); // if bar isn't implemented the compiler would warn/break

注意:我的 Java 不太好,对于任何语法或其他错误,我深表歉意,但我希望你明白这一点。

总而言之,正如我所见,在这两种情况下,两种语言都可以实现多态性,对吧?现在如果对于 Javascript 示例是这样,如何保护它不被破坏,是否有任何模式或技巧? typeof this.bar === function 有效吗?如果是这样,如果程序员忘记了,谁来保证软件质量,我问这种问题是因为Java有编译器警告程序员错误,JS有类似的东西,一些质量检查工具吗?

【问题讨论】:

标签: javascript oop functional-programming typeof duck-typing


【解决方案1】:

Javascript 是一种动态交互* 语言。没有编译器步骤来检查引用。一些工具(jsline)和 IDE(VS、Webstorm)可以为您执行一些设计时检查,但没有真正的类型安全。这在很大程度上被视为一项功能,而不是错误。

有一系列技巧可以解决这个问题(.hasOwnProperty、typeof x === 'function'、存储自引用、上下文绑定),但大多数情况下,如果你想要类型安全,你想要不同的语言。

我的推荐是Typescript。它具有类似 Java/C 的语法,具有一些熟悉的 OOP 功能,例如类、接口(因此,理智的多态性)和泛型类型,并且可以立即转译为 javascript。

【讨论】:

  • “这在很大程度上被视为一项功能,而不是错误。”在我看来,它使语言更灵活,但也更容易出错。
  • 我的背景是 oop/框架编程,所以我倾向于从潜在缺陷的角度来看待动态语言的灵活性 :)
【解决方案2】:

如果您使用构造函数来创建对象,则可以使用 Javascript 的内置类成员发送检查功能。下面是一个例子。

class MyClass {
  bar() { console.log("Lets got to the bar!")}
}

function foo() {
  if ( this instanceof MyClass ) {
   this.bar();
  }
  else {
    console.log('this is not a member of the MyClass');
  }
}

foo.call(new MyClass);

请注意,Javascript 的类型检查非常不可靠,您可能不应该使用它。如果您的对象在其原型链中的任何位置都包含与您正在测试其成员资格的类相同的原型,则 instanceof 将返回 true。

又快又脏的鸭子打字示例

如果你给它一个没有你正在检查的属性的对象,这会抛出,但你明白了。

class MyClass {
   constructor() {
     this.feathers = 'white';
     this.feet = 'webbed';
   }

  bar() { console.log("Lets got to the bar!")}
}

function foo() {
  if (
    this.hasOwnProperty('feathers') && 
    this.hasOwnProperty('feet') && 
    this.feathers === 'white' &&
    this.feet === 'webbed'
  )
  {
    this.bar();
  }
  else {
    console.log('this is not a member of the MyClass');
  }
}

foo.call(new MyClass);

【讨论】:

  • 不过,你会在 JS 中使用鸭子类型作为界面
  • 那么,您在这里解决的问题仅在使用原型时才适用?如果我猜对了,鸭子类型是当你放置属性时,其唯一目的是验证一个对象是否使用了正确的对象并且它包含想要的方法 bar(),或者?
  • 查看instanceof 的工作原理,您将根据它与原型的关系回答您自己的问题。在 Duck 类型中,您不会将属性放在对象上以确定其类型。您尝试通过自己的测试来确定它的类型,以确定它是否是正确的类型。你如何做鸭子打字取决于你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 2021-04-03
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多