如何从函数覆盖构造函数属性

时间:2014-01-03 03:35:41

标签: javascript node.js constructor xmldataprovider jasmine-node

我是JavaScript编程的新手,我甚至不知道如何询问Google,所以我将详细描述我想要实现的目标。

我正在使用node.js和xml2js模块为jasmine创建DataProvider类,它解析简单的XML文件:

<Tests>
    <Test name="test1">
        <values>2,4,6</values>
        <expectations>1,2,3</expectations>
    </Test>
    <Test name="test2">
        <values>8,10,12</values>
        <expectations>4,5,6</expectations>
    </Test>
</Tests>

我希望DataProvider构造函数能够立即解析XML并在this.testData中显示结果。 脚本是:

var fs = require('fs'),
    xml2js = require('xml2js'),
    util = require('util');

var DataProvider = function(dataPath) {
    this.dataPath = dataPath;
    this.testData;

    fs.readFile(this.dataPath, function(err, data) {
        var parser = new xml2js.Parser();
        parser.parseString(data, function(err, result) {
            //console.log(util.inspect(result, false, null));
            this.testData = result;
        });
    });
};

我正在使用它如下:

var dp = new DataProvider("C:\\data2.xml");
console.log(dp.testData);

当我运行脚本>node script.js时,我收到了undefined。 当我取消注释console.log(util.inspect(result, false, null));我正在接收

undefined
{ Tests: 
   { Test: 
      [ { '$': { name: 'test1' },
          values: [ '2,4,6' ],
          expectations: [ '1,2,3' ] },
        { '$': { name: 'test2' },
          values: [ '8,10,12' ],
          expectations: [ '4,5,6' ] } ] } }

所以一般情况下都有效,但如何将result分配给this.testData

这与this.testData的范围有关吗?

1 个答案:

答案 0 :(得分:1)

JavaScript大量使用异步范例,所以当你读取文件时 - 你提供的函数作为回调将在自己的范围内执行。 this与范围有关,因此您将失去它。在您尝试引用this.testData之后,实际上不会引用DataProvider对象,而是您为parseString提供的匿名函数的范围。

因此,有很多方法可以克服,最简单的方法是将this保留在较高范围的变量中,以便您可以引用它,例如调用它self,某些开发者更喜欢{{1} }}

that

或者使用var DataProvider = function(dataPath) { this.dataPath = dataPath; this.testData; var self = this; fs.readFile(this.dataPath, function(err, data) { var parser = new xml2js.Parser(); parser.parseString(data, function(err, result) { //console.log(util.inspect(result, false, null)); self.testData = result; }); }); }; ,但这里的缺点是它必须使用两次(因为你有两个范围来'旅行':

.bind