首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >可以在Javascript中以编程方式更改词法作用域吗?

可以在Javascript中以编程方式更改词法作用域吗?
EN

Stack Overflow用户
提问于 2018-08-22 01:22:03
回答 4查看 414关注 0票数 4

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

代码语言:javascript
复制
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();

结果:

代码语言:javascript
复制
Hello John // Is there a workaround to get "Hello Travis"?
Hello John

硬编码的解决方案: (我不想重复了)

代码语言:javascript
复制
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。

注意:调用和绑定函数允许您更改context ()not scope

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-08-22 06:07:18

简短回答:是的,你可以:-D,但不推荐这样做。

详细答案:在Javascript中,词法作用域是由在代码中编写函数声明的位置定义的,为了在运行时修改词法作用域,您应该使用eval function (尽管它将略微减少performance ):

代码语言:javascript
复制
var name = 'John';

function log() {
    console.log('Hello ' + name );
}
function greetTravis() {
    var name = 'Travis';

    eval( log.toString() ); // <==== The added code.

    log();

}

greetTravis();
log();

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

票数 1
EN

Stack Overflow用户

发布于 2018-08-22 01:26:49

对于您想要的结果,您只需重构log,使其采用您希望其记录的名称。

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

代码语言:javascript
复制
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);

票数 2
EN

Stack Overflow用户

发布于 2018-08-22 01:49:59

我认为没有那么简单。

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

我想你想要的是

代码语言:javascript
复制
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成为对象的情况下,您可以在log()中检查this.name,如果存在,则使用它,否则使用name

代码语言:javascript
复制
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()

//用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 "));//将输出作为欢迎Niladri返回到WB中的纽敦加尔各答

call()方法中的第一个参数设置"this“值,该值是在其上调用函数的对象。在本例中,它是上面的"obj“对象。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51953812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档