Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将作用域传递给回调函数/绑定_Javascript_Scope_Closures - Fatal编程技术网

Javascript 将作用域传递给回调函数/绑定

Javascript 将作用域传递给回调函数/绑定,javascript,scope,closures,Javascript,Scope,Closures,我试图将函数作用域传递给回调方法。我遇到的问题是,我得到的是对象范围,它不能让我访问原始函数中的参数和局部变量。我对“this”的理解是指当前上下文(无论它是窗口还是某些对象)以及本地声明的变量和参数。[引用Richard Cornford在“执行上下文”部分的出色工作]。我还了解JavaScript中的变量具有函数作用域(如果它们在函数中声明,则只能从该函数中访问) 基于这种理解,在一个新的环境中,我尝试编写一个模式,我为我以前的雇主做了很多工作,调用了一个异步方法,指定了一个回调处理程序并传

我试图将函数作用域传递给回调方法。我遇到的问题是,我得到的是对象范围,它不能让我访问原始函数中的参数和局部变量。我对“this”的理解是指当前上下文(无论它是窗口还是某些对象)以及本地声明的变量和参数。[引用Richard Cornford在“执行上下文”部分的出色工作]。我还了解JavaScript中的变量具有函数作用域(如果它们在函数中声明,则只能从该函数中访问)

基于这种理解,在一个新的环境中,我尝试编写一个模式,我为我以前的雇主做了很多工作,调用了一个异步方法,指定了一个回调处理程序并传递了我当前的作用域,希望它在回调方法中可用。在我目前的环境中,我发现情况并非如此。(披露:我在以前的环境中使用ExtJS……让我现在觉得我对框架有点太过舒适了,对正在发生的事情做出了假设)

我的简单测试代码演示了我正在尝试做的事情和不起作用的事情

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/o
    var
    …现在此代码相当复杂,并且隐藏了该变量的事实
    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);