Javascript'新'对象在异步函数中的'this'

时间:2017-02-28 13:03:36

标签: javascript node.js scope this

我正在研究Marc Wandscheider的'Learning Node.JS'。我已经为一个类复制了这段代码并调用了;

let fs = require('fs');
function FileObject() {
    this.filename = '';
    this.file_exists = function(callback) {
        console.log('About to open: ' + this.filename);
        fs.open(this.filename, 'r', function(err, handle) {
            if (err) {
                console.log('Can\'t open: ' + this.filename);
                callback(err);
                return;
            }
            fs.close(handle, function() {});
            callback(null, true);
        });
    };
}
let fo = new FileObject();
fo.filename = 'file_that_does_not_exist';
fo.file_exists((err, results) => {
    if (err) {
        console.log('\nError opening file: ' + JSON.stringify(err));
        return;
    }
    console.log('file exists!!!');
});

运行时输出

About to open: file_that_does_not_exist
Can't open: undefined

undefined是因为fs.open()方法的异步性质。作者通过添加变量来对此进行更正,以便将其存储在let self = this;

我想使用bind(this);代替,但无法解决如何做到这一点!是否有使用self黑客的替代方法?

1 个答案:

答案 0 :(得分:2)

您的问题的答案是,您可以在传递给.bind的函数上调用fs.open,以便正确绑定this

fs.open(this.filename, 'r', function (err, handle) {
    if (err) {
        console.log('Can\'t open: ' + this.filename);
        callback(err);
        return;
    }
    fs.close(handle, function() {});
    callback(null, true);
}.bind(this));  // <-- here

使用self.bind的替代方法是使用箭头函数,它提供词法范围:

let fs = require('fs');
function FileObject() {
    this.filename = '';
    this.file_exists = function(callback) {
        console.log('About to open: ' + this.filename);
        //                            right here --v
        fs.open(this.filename, 'r', (err, handle) => {
            if (err) {
                console.log('Can\'t open: ' + this.filename);
                callback(err);
                return;
            }
            fs.close(handle, function() {});
            callback(null, true);
        });
    };
}
let fo = new FileObject();
fo.filename = 'file_that_does_not_exist';
fo.file_exists((err, results) => {
    if (err) {
        console.log('\nError opening file: ' + JSON.stringify(err));
        return;
    }
    console.log('file exists!!!');
});

浏览器友好示例:

&#13;
&#13;
let fs = {
  open: function(filename, type, callback) {
    callback(new Error());
  }
};

function FileObject() {
  this.filename = '';
  this.file_exists = function(callback) {
    console.log('About to open: ' + this.filename);
    //                            right here --v
    fs.open(this.filename, 'r', (err, handle) => {
      if (err) {
        console.log('Can\'t open: ' + this.filename);
        callback(err);
        return;
      }
      fs.close(handle, function() {});
      callback(null, true);
    });
  };
}
let fo = new FileObject();
fo.filename = 'file_that_does_not_exist';
fo.file_exists((err, results) => {
  if (err) {
    console.log('\nError opening file: ' + JSON.stringify(err));
    return;
  }
  console.log('file exists!!!');
});
&#13;
&#13;
&#13;