【问题标题】:Call ES5 class method from static method从静态方法调用 ES5 类方法
【发布时间】:2017-09-14 10:59:00
【问题描述】:

我想从一个在没有实例的情况下调用的静态函数中调用一个内部函数,如下所示:

Foo.Bar = function (options) {

    Autodesk.Viewing.Extension.call(this, options);

    ...

    this.innerFunc = function innerFunc(){
      ...
    }
};

Foo.Bar.prototype.constructor =
    Foo.Bar;

Foo.Bar.SomeStaticFunc = function () {
    innerFunc();
}

使用:Foo.Bar.SomeStaticFunc();

但我得到SomeStaticFunc is not a function

示例here 为类使用了一个变量,例如var Foo.Bar = function (options) {...,但这与创建类的实例并调用内部函数不一样吗?

let x= new Foo.Bar(options);
x.innerFunc();

还有其他方法吗?

PS:我知道 ES6 类,但我现在不想将这个类迁移到 ES6,因为它不是完全直截了当的。

【问题讨论】:

  • 使用对象字面量,否则需要使用new
  • @SterlingArcher 的对象文字,您的意思是像我链接的示例中一样?
  • 这没有任何意义。您的 innerFunc 仅为实例创建 - 没有实例绝对不可能调用它。
  • 所以innerFunc 以及它调用的所有函数也必须是静态的才能正常工作?如果没有类的实例,我将如何调用它们? @Bergi
  • 要么将它们全部设为静态,全部设为特定于实例,要么让实例方法调用静态方法。

标签: javascript static ecmascript-5


【解决方案1】:

嗯...您似乎不知道 JavaScript 内部是如何工作的,所以这里有一个快速回顾。 :)

  • JavaScript 一种面向对象的语言。对象字面量就是对象,数组就是对象,函数就是对象等等。

  • JavaScript 不是基于类的语言。你可以说:“嘿,我在 ES6 中看到了 classextends 关键字!”。是的,但这只是语法糖。 JavaScript 不像 Java 那样基于类,它基于原型

使用 ES5 语法,有两种方法可以创建所谓的“类”:

  • 对象字面量
  • 构造函数

当您使用对象字面量时,您的类如下所示:

var myClass = {
  myAttribute: "foo",
  myMethod: function () {
    return "bar";
  }
};

当你使用构造函数时,你的类看起来像这样:

function MyClass() {
  this.myAttribute = "foo";
  this.myMethod = function () {
    return "bar";
  };
}

这两种方法之间当然存在差异。使用对象字面量,您有一种 Singleton,其中属性在某种程度上都是静态的。使用构造函数,您可以生成其属性将由 this 关键字引入的实例。示例:

var myInstance = new MyClass();
console.log(myInstance);

此实例将在其自己的属性中包含“myAttribute”和“myMethod”。这意味着这些属性与实例相关联。如果你想调用这个方法,你必须这样做:

myInstance.myMethod();

到目前为止一切都很好......但是我们之前所做的事情有问题。 this.myMethod 将为MyClass 的每个实例一次又一次地创建,并且始终相同。更好的处理方法是将其放入 原型 中,以便所有实例共享:

function MyClass() {
  this.myAttribute = "foo";
}

MyClass.prototype.myMethod = function () {
  return "bar";
};

这好多了,但myMethod 仍然与MyClass 实例绑定...

现在我想创建一个静态方法。根据定义,我们的静态方法将绑定到类,而不是它的实例:

MyClass.myStaticMethod = function () {
  return "baz";
};

很好。在这里,为了实验,我想做这样的事情:

MyClass.myStaticMethod = function () {
  myMethod();
};

这不起作用。为什么?事实上,myMethod 既不存在于给定范围内,也不存在于外部范围内。 myMethod 已在另一个函数(构造函数)中声明,并且没有返回,因此从外部是不可见的。而且这个函数已经放在MyClass的原型里面了。这意味着它在全局范围内不可用,而仅在 MyClass 的实例上可用。当你考虑它时,它是非常合乎逻辑的。例如,当你想调用数组方法(Array.prototype 中的方法)时,这样做是没有意义的:

push('test');
reverse();
includes('a');

您必须在数组(Array 的实例)上调用这些方法。

[].push('test');
['foo', 'bar', 'baz'].reverse();
['a', 'b'].includes('a');

【讨论】:

  • “JavaScript 不像 Java 那样基于类,它基于原型”——这是一个有争议的说法。从建模的角度来看,它在引擎盖下的实现方式并不重要。一切都是 CPU 指令和寄存器的“语法糖”。
  • @zerkms 你是对的,但 Java 一直考虑到类。在 Java 中创建程序时,必须创建一个类。 JavaScript 非常不同,它是围绕原型构建的。我同意,你不需要知道一切是如何在幕后工作的,但这对于使用 JavaScript 非常有用(ES6 仍然不完全支持)。由于 JavaScript 正在成为一种适用于所有事物的语言,因此越来越多的开发人员使用它,他们没有时间学习它,并且认为他们可以严格应用他们对基于类的语言的了解。这会导致很多错误...
  • "但这对于使用 JavaScript 真的很有用" --- 我每天都在做很多 JS,而且我还没有以任何形式明确地自己处理 prototypes 以获得更多信息2年以上。我使用当前标准中定义的“类”,并且不了解底层并不会使我的效率降低或提高:我只是使用类。 “这会导致很多错误”——好吧,我倾向于不同意。如果您不处理原型 - 它会让您的生活更轻松。
  • 我假设你使用了很多库,这很好。事实上,在这种情况下,没有必要直接与原型(例如 jQuery)进行斗争。事实上,当你想在 Vanilla JS 中创建一些东西时,你只需要与原型作斗争。这个问题是关于 ES5 的,所以我回答了关于 ES5 的问题。当然,如果您构建现代 Web 应用程序,您可以使用 React 或 Angular... ^^
  • @Badacadabra 我也认为没有必要了解原型。 JS 是一种 OO 语言,所有原则都适用。在我看来,JS 和 Java 的唯一区别就是“语法糖”。如果您了解 OOP,您可以很好地处理两种语言。
猜你喜欢
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
相关资源
最近更新 更多