Javascript 将作用域传递给回调函数/绑定
我试图将函数作用域传递给回调方法。我遇到的问题是,我得到的是对象范围,它不能让我访问原始函数中的参数和局部变量。我对“this”的理解是指当前上下文(无论它是窗口还是某些对象)以及本地声明的变量和参数。[引用Richard Cornford在“执行上下文”部分的出色工作]。我还了解JavaScript中的变量具有函数作用域(如果它们在函数中声明,则只能从该函数中访问) 基于这种理解,在一个新的环境中,我尝试编写一个模式,我为我以前的雇主做了很多工作,调用了一个异步方法,指定了一个回调处理程序并传递了我当前的作用域,希望它在回调方法中可用。在我目前的环境中,我发现情况并非如此。(披露:我在以前的环境中使用ExtJS……让我现在觉得我对框架有点太过舒适了,对正在发生的事情做出了假设) 我的简单测试代码演示了我正在尝试做的事情和不起作用的事情Javascript 将作用域传递给回调函数/绑定,javascript,scope,closures,Javascript,Scope,Closures,我试图将函数作用域传递给回调方法。我遇到的问题是,我得到的是对象范围,它不能让我访问原始函数中的参数和局部变量。我对“this”的理解是指当前上下文(无论它是窗口还是某些对象)以及本地声明的变量和参数。[引用Richard Cornford在“执行上下文”部分的出色工作]。我还了解JavaScript中的变量具有函数作用域(如果它们在函数中声明,则只能从该函数中访问) 基于这种理解,在一个新的环境中,我尝试编写一个模式,我为我以前的雇主做了很多工作,调用了一个异步方法,指定了一个回调处理程序并传
function myHandler(data, ctx) {
console.log('myHandler(): bar: ' + bar); // <- prob: bar undefined
console.log(JSON.stringify(data));
}
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback.call(scope||this,result, scope);
}
}
}
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler, this); // scope object is this
}
lookup();
函数myHandler(数据,ctx){
log('myHandler():bar:'+bar);//顺便说一句,关于代码中的作用域:
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler, this); // this here points to window object and not to the function scope
}
因此,这与写作是一样的:
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler, window);
}
这是因为您全局定义了查找函数。在doWork
函数中,当您编写this
时,它指向MySvcWrap
对象(因为该函数是在该对象中定义的)
如果回调函数必须查看bar
变量,那么它应该在相同的范围内定义,如下所示
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback.call(scope||this,result, scope);
}
}
}
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang',
function (data, ctx) {
console.log('myHandler(): bar: ' + bar);
console.log(JSON.stringify(data));
},
this); // scope object is this
}
lookup();
在本例中,您将匿名函数作为回调发送,它是在查找函数中定义的,因此它可以访问其局部变量;我的控制台在此cae中显示:
myHandler(): bar: food
{"colors":["red","green"],"name":"Jones","what":"thang"}
为了便于支持,您可以在查找函数中定义myHandler:
function lookup() {
var bar = 'food'; // local var
var myHandler = function(data, ctx) {
console.log('myHandler(): bar: ' + bar);
console.log(JSON.stringify(data));
};
MySvcWrap.doWork('thang', myHandler, this); // scope object is this
}
另一方面,为什么一个函数应该访问另一个函数的局部变量?也许可以重新设计
使代码正常工作的另一种方法是使用匿名函数,而不是查找(如果只声明并执行该函数一次,则可以正常工作):
结果是相同的,但不再有查找函数
还有一个使其工作的想法……实际上,您需要在定义bar变量的同一范围内定义回调处理程序,这样做可能有点棘手,但也可以选择:
function myHandler(bar) { // actually in this case better to call it createHandler
return function(data, ctx) {
console.log('myHandler(): bar: ' + bar);
console.log(JSON.stringify(data));
}
}
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback.call(scope||this,result, scope);
}
}
}
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler(bar), this); // scope object is this
}
关于JavaScript作用域和闭包的阅读资料也很少:
-关于主题的介绍非常好
如果代码的结构是这样的,那么它就可以工作
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback.call(scope||this,result, scope);
}
}
}
function lookup() {
var bar = 'food'; // local var
function myHandler(data, ctx) {
console.log('myHandler(): bar: ' + bar); // <- prob: bar undefined
console.log(JSON.stringify(data));
}
MySvcWrap.doWork('thang', myHandler, this); // scope object is this
}
lookup();
function myHandler(data, bar, ctx) {
console.log('myHandler(): bar: ' + bar); // <- prob: bar undefined
console.log(JSON.stringify(data));
}
MySvcWrap = {
doWork: function(p1, callback) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback(result);
}
}
}
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler.bind(this, bar)); // callback function is bound to the scope
}
lookup();
MySvcWrap={
doWork:函数(p1、回调、作用域){
var result={colors:['red','green'],name:'Jones',what:p1};
如果(回调){
callback.call(作用域| | this,result,scope);
}
}
}
函数查找(){
var bar='food';//本地变量
函数myHandler(数据,ctx){
log('myHandler():bar:'+bar);//我的第一个答案有点快,留下了Maxym在下面的评论中所说的一些空白部分,谢谢你通知我:)这就是我在回去工作之前尝试快速发布的结果:p
在我的第一个答案中,我试图得到的是,如果您想使用绑定从函数myHandler
(不在lookup
的范围内)访问函数lookup
中的变量,那么您必须不使用var
,而是使用this
使用var
只能访问lookup的
私有范围和嵌套在其中的任何函数,这就是其他答案所证明的(可能是最好的途径)
下面是一个更新的示例,说明如何将查找的范围传递给myHandler,而将myHandler完全排除在查找的范围之外。希望这将有助于了解:
“我遇到的问题是,我获取的是对象范围,而对象范围不允许我访问原始函数中的参数和局部变量。”
正如我之前回答的评论中所述,此
可能会变得棘手,如果不像我在第一个示例中那样小心,您最终可能会将内容添加到全局
范围中:(因此,我添加了一点黑客检查,以查看此
的作用域,确保它不是用于演示的
窗口。)
function myHandler(data, ctx) {
console.log('myHandler(): bar: ' + this.bar); // <- must use `this`
console.log('myHandler(): privateBar: ' + this.privateBar); // <- undefined because it's privately scoped
console.log(JSON.stringify(data));
}
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {
colors: ['red', 'green'],
name: 'Jones',
what: p1
};
if (callback) {
callback.call(scope || this, result, scope);
}
}
}
function lookup() {
if(this == window) return lookup.call(lookup); // <- my hack'ish check
var privateBar = 'private food'; // private local var
this.bar = 'food'; // public local var
MySvcWrap.doWork('thang', myHandler, this); // scope object is this
}
lookup();
console.log('global space - bar: ' + this.bar);
函数myHandler(数据,ctx){
console.log('myHandler():bar:'+this.bar);//var bar=this.bar='food';
-在本例中,您在window对象中创建bar
变量,因此它与在查找函数外部声明此变量并在此处定义它相同,或者在没有bar='food'
的情况下定义它,我的意思是w/ovar
…现在此代码相当复杂,并且隐藏了该变量的事实bar
现在也是全局的,我喜欢参数化处理程序方法。
function myHandler(data, bar, ctx) {
console.log('myHandler(): bar: ' + bar); // <- prob: bar undefined
console.log(JSON.stringify(data));
}
MySvcWrap = {
doWork: function(p1, callback) {
var result = {colors: ['red', 'green'], name:'Jones', what: p1};
if (callback) {
callback(result);
}
}
}
function lookup() {
var bar = 'food'; // local var
MySvcWrap.doWork('thang', myHandler.bind(this, bar)); // callback function is bound to the scope
}
lookup();
function myHandler(data, ctx) {
console.log('myHandler(): bar: ' + this.bar); // <- must use `this`
console.log('myHandler(): privateBar: ' + this.privateBar); // <- undefined because it's privately scoped
console.log(JSON.stringify(data));
}
MySvcWrap = {
doWork: function(p1, callback, scope) {
var result = {
colors: ['red', 'green'],
name: 'Jones',
what: p1
};
if (callback) {
callback.call(scope || this, result, scope);
}
}
}
function lookup() {
if(this == window) return lookup.call(lookup); // <- my hack'ish check
var privateBar = 'private food'; // private local var
this.bar = 'food'; // public local var
MySvcWrap.doWork('thang', myHandler, this); // scope object is this
}
lookup();
console.log('global space - bar: ' + this.bar);