- 发生时间:2022-06-16
- 问题描述:
- 开发产线工具时,在类
SerialPortClient中定义了一个 static method_parseData。 - 在这个类的另一个函数中通过
this来调用_parseData时报错:TypeError: this._parseData is not a function。
- 开发产线工具时,在类
- 问题类别:软件开发
- 原因分析:查阅MDN Web docs 关于 static 的文档,发现 js 语法规定 js 类内部的普通函数不能通过
this来直接调用 static method。 - 解决方案:文档中给出了两种解决方案:可以通过
SerialPortClient._parseData或this.constructor._parseData的方式来调用。 - 实施结果:采用第一种解决方案后,可以正常调用函数。
- 经验总结:js 类内部普通函数需要通过
CLASSNAME.STATIC_METHOD_NAME()的方式来调用 js static method。
一个能够复现此问题的 demo 代码
class Foo {
constructor() {
this._count = 0
}
static hi() {
console.log('hello world')
}
display() {
this.hi()
console.log('count:', this._count)
}
}
let foo = new Foo();
foo.display();
在终端使用 node 运行以上脚本,会报以下错误:
$ node static_demo.js
C:\Users\minieye\src\demo\js-static\static_demo.js:11
this.hi()
^
TypeError: this.hi is not a function
at Foo.display (C:\Users\minieye\src\demo\js-static\static_demo.js:11:10)
at Object.<anonymous> (C:\Users\minieye\src\demo\js-static\static_demo.js:17:5)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
at internal/main/run_main_module.js:17:47
关于 js static 的一些补充说明
MDN 文档中介绍了 js 类内部的非 static 方法调用 static 成员时的两种方法:
Static members are not directly accessible using the this keyword from non-static methods. You need to call them using the class name: CLASSNAME.STATIC_METHOD_NAME() / CLASSNAME.STATIC_PROPERTY_NAME or by calling the method as a property of the constructor: this.constructor.STATIC_METHOD_NAME() / this.constructor.STATIC_PROPERTY_NAME
值得注意的是,js 类内部的 static 方法是可以通过 this 来直接调用其他 static 成员的:
In order to call a static method or property within another static method of the same class, you can use the this keyword.
js static method vs Python @staticmethod
我们不妨对比一下 js static method 与 Python staticmethod 的差异。
根据 Python 官方文档关于 @staticmethod 的描述,Python 与 js 的 static method 是类似的,但也有一个差异:
- js 的 static method 只能通过类名字来调用,不能通过类实例来调用; 而 Python 的 static method 可以通过类名字或类实例来调用。
- js 类内部的非 statis method 不能通过
this来直接调用 static method; 而 Python 类内部的非 static method 可以通过self来直接调用 static method。
顺便提一下,Python 还有一个 class method,它的调用方式与 static method 类似,但两者是存在明显区别的:
- A class method takes cls as the first parameter while a static method needs no specific parameters.
- A class method can access or modify the class state while a static method can’t access or modify it.
- In general, static methods know nothing about the class state.
stack overflow 的这个回答 更深入探讨了 Python classmethod 与 static method 的差异,值得阅读。