我对bind
与Meteor.bindEnvironment
的行为以及this
与Meteor.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
与函数的绑定?有正确的用法吗?
答案 0 :(得分:2)
这是真正令人困惑和冗长的句子:
本质上,它允许您创建一个匿名函数,其中“this”的上下文值是函数的范围,该函数的范围是定义箭头函数的外部函数。
通过将其简化为更简洁的语言,可以更容易理解:
它允许您创建一个匿名函数,该函数在词法上与其定义的范围绑定。
________
您提供的示例中没有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函数),你阻止它改变执行功能的背景。