`bind`如何与`Meteor.bindEnvironment`一起工作?

时间:2015-09-28 12:18:44

标签: javascript node.js meteor

我对bindMeteor.bindEnvironment的行为以及thisMeteor.bindEnvironment的范围有点混淆。例如,with arrow functions, arrow functions should maintain the outer scope

  

本质上,它允许您创建一个匿名函数,其中“this”的上下文值是函数的范围,该函数的范围是定义箭头函数的外部函数。

因此,当我使用以下代码时,会出现,但console.log似乎说this是Meteor的范围。

Cylon = new EventEmitter();
Cylon.messages = new Mongo.Collection('_cylon_messages');
Cylon._commands = net.connect(Settings.connection);
Cylon._createConnection = function (name, connection) {
  let socket = net.connect(connection, Meteor.bindEnvironment(() => {
    this.messages.insert({ name: name, message: 'connected'})
  }));
  socket._name = name;
  return socket;
}

我理解的另一个例子是在需要Meteor.bindEnvironment的回调中使用bind。例如:

Cylon.execute = function (routine) {
  check(command, String);
  let future = new Future();
  let done = future.resolver();
  this.once('End', Meteor.bindEnvironment(done.bind(null, routine)));
  this._commands.write(`XQ#${routine}\r`, 'utf8');
  future.wait();
  this.removeListener('End', Meteor.bindEnvironment(done.bind(null, routine)));
  return future;
}

Meteor.bindEnvironment如何处理this与函数的绑定?有正确的用法吗?

1 个答案:

答案 0 :(得分:2)

什么是箭头功能?

这是真正令人困惑和冗长的句子:

  

本质上,它允许您创建一个匿名函数,其中“this”的上下文值是函数的范围,该函数的范围是定义箭头函数的外部函数。

通过将其简化为更简洁的语言,可以更容易理解:

  

它允许您创建一个匿名函数,该函数在词法上与其定义的范围绑定。

________

Arrow Functions解释

您提供的示例中没有console.log - 可能是您在console.log的箭头函数中放置了bindEnvironment,如下所示:

let socket = net.connect(connection, Meteor.bindEnvironment(() => {
    console.log(this);
    // this.messages.insert({ name: name, message: 'connected'});
}));

实际上,上面示例中的this将是对箭头函数的执行上下文的引用。例如:

this.stillInScope = true;
let socket = net.connect(connection, Meteor.bindEnvironment(() => {
    console.log(this.stillInScope); // => 'true'
}));

但是,假设我们将箭头功能更改为匿名功能。在调用上,它不会保持对声明时出现的执行上下文的访问权限:

this.stillInScope = true;
let socket = net.connect(connection, Meteor.bindEnvironment(function () {
    console.log(this.stillInScope); // => 'undefined'
}));

因此,如果此示例的当前执行上下文是Meteor对象,则箭头函数将以词法方式绑定到Meteor对象:

// this instanceof Meteor === true
let socket = net.connect(connection, Meteor.bindEnvironment(() => {
    console.log(this instanceof Meteor); // => 'true'
}));

________

bind方法说明

让我们讨论为什么要使用bind来理解第二个例子中的内容。

bind的第一个参数:执行上下文

在方法上使用bind会生成一个新函数,该函数绑定到第一个参数定义的执行上下文。假设我们在全局执行上下文为window的浏览器中运行它:

let method = function () { 
    console.log(this);
};

method(); // => window

let boundMethod = method.bind('Hello'); // `this` now becomes 'Hello'
boundMethod(); // => 'Hello'

此绑定永远不会改变;不是通过绑定函数内的调用,也不是通过后续调用bind

bind的后续参数:默认参数

在您给出bind的示例中,实际上只是用作速记。我们可以知道这一点,因为给定的执行上下文是null,表示bind仅用于将默认参数应用于函数的方式:

// with `bind`
Meteor.bindEnvironment(done.bind(null, routine))

// without `bind`
Meteor.bindEnvironment(function () {
    done(routine);
});

________

bind如何与Meteor.bindEnvironment合作?

最后,为了回答你的问题,bind本身并没有“合作”。 Meteor.bindEnvironment接受赋予它的函数并将其绑定到由闭包维护的执行上下文,其中最初定义了方法bindEnvironment

An explanation of the purpose of Meteor.bindEnvironment on GitHub

  

bindEnvironment的思想是,当将回调传递给非Meteor代码时,可以让它们在当前上下文中运行。在包含当前光纤的服务器上。因此,如果你发现自己在服务器上的光纤之外,你可能没有足够的调用bindEnvironment!

通过给它一个已经绑定的函数(作为箭头函数或通过传递手动bind ed函数),你阻止它改变执行功能的背景。