是否可以通过Java编程方式更改词法范围?

时间:2018-08-21 17:22:03

标签: javascript scope

我不知道这是否可能,但是,说我们有以下代码:

var name = 'John';

function log() {
    console.log('Hello ' + name );
}

function greetTravis() {
    var name = 'Travis';

    log(); // This function is defined outside greetTravis's scope. 
}


greetTravis();
log();

结果:

Hello John // Is there a workaround to get "Hello Travis"?
Hello John

一种硬编码的解决方案:(我不想重复我自己)

var name = 'John';

function log() {
    console.log('Hello ' + name );
}

function greetTravis() {
    var name = 'Travis';

    log(); // Now, it is defined inside greetTravis's scope. 

    function log() {
        console.log('Hello ' + name );
    }

}


greetTravis();
log();

我要做什么:

我想从log函数访问名称变量(greetTravis()内的一个变量)而不传递变量,也许使用改变log()范围的函数,例如:call / bind。 / p>

  

注意:调用和绑定功能使您可以更改上下文(此), 作用域

4 个答案:

答案 0 :(得分:3)

对于所需的结果,只需重构log,以使其采用您想要记录的名称即可。

仅供参考-window对象具有一个名为name的属性。因此,最好的做法是在代码中不使用name作为全局变量。

var userName = 'John';

function log(val) {
    console.log('Hello ' + val );
}

function greetTravis() {
    var userName = 'Travis';

    log(userName); // This function is defined outside greetTravis's scope. 
}


greetTravis();
log(userName);

答案 1 :(得分:2)

我想没有那么简单的东西。

如果您未在greetTravis中使用var name = 'Travis';,则会覆盖全局值,但是,当第二次调用log();时,它也会记录Hello Travis

我认为您想要的是类似的东西

function createPersonObj(name) {
    return { // this must be on the same line
        name: name
    }
}

var name = 'John';
var personJohn = createPersonObj(name);

function log() {
    console.log('Hello ' + this.name );
}

function greetTravis() {
    var name = 'Travis';
    var personTravis = createPersonObj(name);

    log.call(personTravis);
}

greetTravis();
log.call(personJohn);

如果不使John成为对象,则可以改为在this.name内检查log(),如果存在,请使用它,否则,请使用name

function log() {
    var nameToLog = (this.name !== undefined)
        ? this.name
        : name;
    console.log('Hello ' + nameToLog );
}

来源:https://www.codementor.io/niladrisekhardutta/how-to-call-apply-and-bind-in-javascript-8i1jca6jp

  

检查以下代码示例中的call()

//Demo with javascript .call()

var obj = {name:"Niladri"};

var greeting = function(a,b,c){
    return "welcome "+this.name+" to "+a+" "+b+" in "+c;
};

console.log(greeting.call(obj,"Newtown","KOLKATA","WB"));
// returns output as welcome Niladri to Newtown KOLKATA in WB
     

call()方法中的第一个参数设置“ this”值,该值是在其上调用函数的对象。在这种情况下,它就是上面的“ obj”对象。

     

其余参数是实际函数的参数。

答案 2 :(得分:0)

在这种情况下,log()函数只能访问全局变量名称。为了呈现局部变量,您需要通过参数获取“名称”

答案 3 :(得分:0)

简短的回答:是的,您可以:-D,但是不建议这样做。

详细答案: 在Javascript中,词汇范围是由代码中编写函数声明的位置定义的, 并且为了在运行时修改词法范围,您应该使用eval function(即使它会稍微降低 性能),如下所示:

ok:true
status:200
statusText:"OK"
type:2
_body:"�PNG↵↵IHDR�X:�(��IDATx��6��g��L&��s�I4�ƅ�G\QTQ#���Ib�Ep�w# (�

在这种情况下,使用eval()是完全安全的( eval() isn’t evil )。