【问题标题】:Javascript 'New' object's 'this' in async function异步函数中的Javascript“新”对象的“this”
【发布时间】:2017-07-19 11:13:42
【问题描述】:

我正在学习 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

未定义是因为fs.open() 方法的异步性质。作者通过添加一个变量将其存储在let self = this; 中来纠正这个问题

我想改用bind(this);,但不知道该怎么做!有没有使用self hack 的替代方法?

【问题讨论】:

    标签: javascript node.js scope this


    【解决方案1】:

    您的问题的答案是,您可以在传递给fs.open 的函数上调用.bind,以便正确绑定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!!!');
    });
    

    浏览器友好示例:

    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!!!');
    });

    【讨论】:

    • 这是一个快速的答案。是的,这就是我想要的方式!谢谢。(我会在 9 分钟后将其标记为答案)
    • 只是为了添加一点上下文 - 箭头函数在第 4 版中被添加到 Node 中,因此原帖中引用的书没有使用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    相关资源
    最近更新 更多