带有变量的 Nodejs class

Nodejs class with variables

我在文件中有这个解析器 class:

module.exports = function Parser() {      

    this.myVar = "";

    var parse = function (inputString) {
        this.myVar = "somethingAfterParse";
    }

    return {
        initWithString: function(inputString) {
             parse(inputString)
        },
        name: this.myVar
    };  

};

然后,在"main"文件js中说,我是这样使用解析器的:

var Parser = require("./Parser.js");
var parserInstance = new Parser();
parserInstance.initWithString("somestring");
console.log("Parser var:", parserInstance.myVar);

没有错误,但日志打印出一个空名称.. 为什么?

您可以 return 一个 Parser 类型,而不是 return 一个 匿名 object

module.exports = function Parser() {      
    var self = this;
    self.name = "";

    self.parse = function (inputString) {
        self.name = inputString + " parsed";
    }

    return self;  
};

然后,在"main"文件js中,我是这样使用解析器的:

var Parser = require("./Parser.js");
var parserInstance = new Parser();
parserInstance.parse("something");
console.log("Parser name:", parserInstance.name); // Parser name: something  parsed

我会这样做:

function Parser() {
    this.myVar = "";
}
Parser.prototype.initWithString = function (inputString) {
    this.myVar = "somethingAfterParse";
};

module.exports = Parser;

你的方法,注释

module.exports = function Parser() {
    // public property "myVar" of any new Parser object
    this.myVar = "";

    // anonymous function assigned to private variable "parse"
    var parse = function (inputString) {
        // "this" will likely be the global object here, dangling error
        this.myVar = "somethingAfterParse";
    }

    // return API object - unnecessary and makes debugging harder (*)
    return {
        // anonymous function that calls private "parse" function
        initWithString: function(inputString) {
             // calling parse without defining "this", definitely an error (**)
             parse(inputString)
        },
        // the above is equivalent to and therefore better written as
        // initWithString: parse,

        // copy of (!) public property myVar, definitely an error (***)
        name: this.myVar
    };  
};

当您省略冗余位(并利用原型链)时,您最终会得到我上面建议的结果。


* 我知道这是定义对象的 public 接口的流行方法。我个人不是很喜欢。从 JS 构造函数返回一个对象有效地破坏了 new 运算符的有用性:

  • 您使对象的用户无法访问在构造函数内部之前分配给 this 的所有内容,例如您的 this.myVar.
  • 你得到一包没有类型信息的属性。从技术上讲这是可行的,但在调试过程中并不好。比较:

    function A() {
        this.a = "A";
        return {
            a: "a"
        };
    }
    
    function B() {
        this.b = "B";
    }
    
    new A(); // Object {a: "a"}
    new B(); // B {b: "B"}
    

** this 函数内部将引用函数 上调用的任何对象(上下文)。

通常点符号会为您做到这一点:object.method()method 中将 this 设置为 object

但是您不要对任何对象调用 parse() 函数。任何在没有上下文的情况下调用的函数都在全局对象的上下文中运行(在浏览器中是 Window)。

您可能需要在前面使用 var self = this; 并在 initWithString 正文中使用 parse.apply(self, arguments) 来指定上下文。

最后整个 "let's return an object as the API" 方法让事情变得比他们需要的更困难。

*** 在 JavaScript 中,原始类型总是按值赋值。就像数字或布尔值一样,您不能引用字符串。将它们分配给其他变量会复制它们。

你必须使用 .call.apply

module.exports = function Parser() {

    this.name = "";

    var parse = function(inputString) {
        this.name = "somethingAfterParse";
    }

    return {
        initWithString: function(inputString) {
            parse.call(this, inputString)
        },
        name: this.name
    };

};