Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/373.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
是否可以从已用完闭包的eval访问闭包变量(不使用此.variable)?Javascript(Node.js) 最佳方式(国际海事组织):_Javascript_Closures_Eval - Fatal编程技术网

是否可以从已用完闭包的eval访问闭包变量(不使用此.variable)?Javascript(Node.js) 最佳方式(国际海事组织):

是否可以从已用完闭包的eval访问闭包变量(不使用此.variable)?Javascript(Node.js) 最佳方式(国际海事组织):,javascript,closures,eval,Javascript,Closures,Eval,这个问题已经更新,如果有人需要,我会在这里发布我是如何结束测试的 下面的原始问题 我知道这可能不太可能,但我会清楚地解释我希望它工作的原因和方式: 为什么? 我想做一些测试,当某些东西缺失时不会失败,如果存在或不存在,我不想测试所有东西 例如: expect('Something', existingClosureVar.notExistingProperty.toString()).toBe('ho ho'); var callingFn = function(){ var cont

这个问题已经更新,如果有人需要,我会在这里发布我是如何结束测试的

下面的原始问题

我知道这可能不太可能,但我会清楚地解释我希望它工作的原因和方式:

为什么? 我想做一些测试,当某些东西缺失时不会失败,如果存在或不存在,我不想测试所有东西

例如:

expect('Something', existingClosureVar.notExistingProperty.toString()).toBe('ho ho');
var callingFn = function(){
    var context = {b: 1};
    var evalString = 'b'; // prints 1
    expect(context, evalString)
}
var expect = function(context, evalString){
        var fn = function(){
                console.log(eval('this.' + evalString))
        }
        fn.call(context);

}
callingFn()​
这将引发如下错误:TypeError:无法调用未定义的方法“toString”。

解决这个问题很容易,但也很痛苦

if(existingClosureVar && existingClosureVar.notExistingProperty && existingClosureVar.notExistingProperty.toString){
     expect('Something', existingClosureVar.notExistingProperty.toString()).toBe('ho ho');
}
好吧,但如果它不存在,我甚至没有注意到考试不及格!可能存在一些更详细的解决方法,但会使代码越来越大,而我只需要一件简单的事情,这应该是最短的事情

我们应该如何取而代之? expect函数应该能够访问闭包的局部变量,以实现此功能。它将在try-catch上下文中运行字符串,如果失败,测试也将失败

正是我想要的: 如果我提供一个上下文,它是有效的,但是。。。 这需要我使用“this.”符号来获取变量。因为很多函数是异步的,并且函数的上下文没有维护(可以维护,但是需要做更多的工作)(或者我们可以使用闭包变量来保存上下文变量)

例如:

expect('Something', existingClosureVar.notExistingProperty.toString()).toBe('ho ho');
var callingFn = function(){
    var context = {b: 1};
    var evalString = 'b'; // prints 1
    expect(context, evalString)
}
var expect = function(context, evalString){
        var fn = function(){
                console.log(eval('this.' + evalString))
        }
        fn.call(context);

}
callingFn()​
我发现了一个丑陋的解决方案: 可行的解决方案,但仍然过于冗长: 我还必须在代码前放4行,但这里是:

共享上下文:

本地变量+字符串:


//例如Google Chrome,它可能无法在其他浏览器中运行。

不,
eval
'd代码在全局范围内运行。为什么需要再次使用eval

使用匿名函数而不是将代码放在字符串中,所有与作用域相关的问题都将消失

var callingFn = function() {
    var a = 99;
    // remember, the eval can't sit here, must be outside
    expect(this, function() {
        console.log(a);
    });
}
var expect = function(context, callable) {
    try {
        callable.call(context);
    }
    catch(ex) {
        // handle exception
    }
}

演示:

总之,。您无法从
eval
code访问闭包中的变量

使用
eval
Function
构造函数创建的函数始终在全局范围(或在严格模式下,未定义范围)中运行。这是无法避免的

此外,您不能从函数外部(或函数内部)访问函数的作用域。这是因为JavaScript具有静态作用域;范围在声明时是固定的。函数不能更改其作用域链

如果您只是希望在属性未定义的情况下测试失败,最简单的方法可能是:

if (obj && obj.prop) expect('Some Test', obj.prop) ...
else fail('Some Test');
或者使用其调用包装在
try
中的回调

expect('Some Test', function() {
    return obj.prop;
}).toBe('some value');
expect
可以使用回调的返回值,或者如果您知道始终会定义有问题的标识符,则允许您传递一个简单的值

function expect(name, o) {
    var expectedValue;
    if (typeof o == 'function') {
        try { expectedValue = o(); }
        catch(ex) { /* fail here */ }
    } else expectedValue = o;

    ...
}
因此,您可以通过任何一种方式调用
expect

function callingFn() {
    var localVar = 1, someObj = {};

    expect('Test var', localVar).toBe(1);
    expect('Test obj', function() { return someObj.missingProp.toString(); }).toBe('value');
}

这也是一个很好的想法,但是如果可能的话,我真的希望不必为每个expect定义一个新函数,因为这就是我提出这个问题的原因。我的目标是尽可能使用更少的代码和更干净的代码,即使我必须使用eval。。但是谢谢你的回答。这就是如何做到的。不能使用eval编写干净的代码。尤其是当您需要访问正在定义代码字符串的本地范围时。但是使用“if(obj&&obj.prop)”或“try{function}catch(){}”仍然需要详细说明IMO。这就是为什么我选择要求使用最不详细的方法来完成此操作。感谢您的回复;)这个“expect('Test obj',function(){return someObj.missingProp.toString();}).toBe('value');”和“expect('Test obj','someObj.missingProp.toString()).toBe('value');”之间的区别并没有那么大,我知道,但我不想在每个expect调用中到处都看到函数。坦白地说,我认为你不会比我在最后一个例子中看到的更好。由于作用域是静态的,并且eval总是在全局作用域中运行,如果没有在目标变量的作用域中定义函数,就不可能实现目标。此外,这是JavaScript;没有必要担心匿名回调函数。我不担心,我只是想知道是否有可能进行更干净的测试。为每个expect变量使用函数有点太多了sEh-它是额外的18个字符。依我看,这比你的问题中的任何一个选择都要少。
var callingFn = function() {
    var a = 99;
    // remember, the eval can't sit here, must be outside
    expect(this, function() {
        console.log(a);
    });
}
var expect = function(context, callable) {
    try {
        callable.call(context);
    }
    catch(ex) {
        // handle exception
    }
}
if (obj && obj.prop) expect('Some Test', obj.prop) ...
else fail('Some Test');
expect('Some Test', function() {
    return obj.prop;
}).toBe('some value');
function expect(name, o) {
    var expectedValue;
    if (typeof o == 'function') {
        try { expectedValue = o(); }
        catch(ex) { /* fail here */ }
    } else expectedValue = o;

    ...
}
function callingFn() {
    var localVar = 1, someObj = {};

    expect('Test var', localVar).toBe(1);
    expect('Test obj', function() { return someObj.missingProp.toString(); }).toBe('value');
}