我有一个包含文件的目录,我需要解析并保存在JavaScript对象数组中。在构造函数中,只要我在下面的代码中达到第2点,this
就会变成undefined
而在第3点我没有访问this.data
。修复代码并实现目标的最佳方法是什么?
function Service(path) {
this.data = [];
console.log(this); // point 1
fs.readdir(path, function (err, files) {
console.log(this); // point 2
files.forEach(function (file) {
fs.readFile(path + file, function (err, data) {
parseString(data, function (err, result) {
this.data.push(result); // point 3
});
});
}, this);
});
}
Service.prototype.getData = function () {
// do something with `this.data` and return the result
};
我尝试将this
保存为self
,但最后self
以正确的数组结束,而this
则没有:
function Service(path) {
var self = this;
this.data = [];
fs.readdir(path, function (err, files) {
files.forEach(function (file) {
fs.readFile(path + file, function (err, data) {
parseString(data, function (err, result) {
self.data.push(result);
});
});
});
});
setTimeout(function () {
console.log(this); \\ point x
console.log(self); \\ point y
}, 3000);
}
Service.prototype.getData = function () {
// do something with `this.data` and return the result
};
答案 0 :(得分:3)
this
对象在您从函数的范围更改为另一个范围时随时更改。
您可以通过将所需的this
对象保存到变量(在我的示例中为self
)来解决此问题:
function Service(path) {
var self = this;
self.data = [];
console.log(this); // point 1
fs.readdir(path, function (err, files) {
console.log(self); // point 2
files.forEach(function (file) {
fs.readFile(path + file, function (err, data) {
parseString(data, function (err, result) {
self.data.push(result); // point 3
});
});
});
});
}
Service.prototype.getData = function () {
var self = this;
setTimeout(function () {
console.log(self.data);
}, 100);
};
var serv = new Service();
serv.getData(); // your array
请参阅documentation on Mozilla for this
。
要查看示例,请参阅this fiddle。
答案 1 :(得分:3)
作为Vsevolod答案的替代方案,您还可以使用bind。
function Service(path) {
this.data = [];
console.log(this); // point 1
fs.readdir(path, function (err, files) {
console.log(this); // point 2
files.forEach(function (file) {
fs.readFile(path + file, function (err, data) {
parseString(data, function (err, result) {
this.data.push(result); // point 3
}.bind(this));
});
}, this);
}.bind(this));
}
绑定比使用闭包更慢,但这只会在非常紧凑的循环中非常重要,您需要进行大量的迭代,并且在大多数情况下不太可能成为问题。
答案 2 :(得分:1)
this
指的是当前的'上下文。
在你的例子中,你可以保存'外部' this
到本地变量
function Service(path) {
var $this = this;
this.data = [];
console.log(this); // point 1
fs.readdir(path, function (err, files) {
console.log($this); // point 2
files.forEach(function (file) {
fs.readFile(path + file, function (err, data) {
parseString(data, function (err, result) {
$this.data.push(result); // point 3
});
});
}, $this);
});
}
使用bind
时PS也不被禁止,将this
分配给局部变量的解决方案看起来更优雅,并确保您不会忘记将另一个bind
添加到回调
答案 3 :(得分:1)
我不确定为什么会出现这种情况,但如果您在原型中执行this.data = this.data
或self = this
,则会输出正确的值。否则,它在创建时返回整个Service实例。以下是您可以尝试使用虚拟Service
和getData
示例的代码段。
function Service(array) {
var self = this;
this.data = [];
console.log(this); // point 1
array.forEach(function(item) {
self.data.push(item); // point 2
});
}
Service.prototype.getData = function() {
self = this;
return self.data;
};
var serv = new Service(['bob', 'aerith']);
console.log(serv.getData());