是否可以在JavaScript中更改函数运行时范围

Is it possible to change function runtime scope in JavaScript?

本文关键字:函数 运行时 范围 JavaScript 是否      更新时间:2023-09-26

我正在开发JavaScript库,同时需要相应地加载不同的模块,我使用回调来加载不同的脚本:

只需在页面中添加main脚本:

<script type="text/javascript" src="main.js"></script>

main.js:

(function () {
    var actionForT2 = function (fun) {
        fun && fun.apply(this);
    }
    var loadCallback = function (name, obj) {
        if (name == "t2") {
            actionForT2(obj);
        }
    }
    window.__jsload = loadCallback;
    var loadJs = function (js) {
        var head = document.head || document.getElementsByTagName('head')[0];
        var script = document.createElement("script");
        script.setAttribute("src", js);
        script.setAttribute("type", "text/javascript");
        head.appendChild(script);
    }
    loadJs("js/t2.js");
})();

t2.js:

__jsload('t2', function () {
    console.info("t2 loaded");
    console.info(loadJs);
})

现在t2.js将按预期加载。我得到了输出:

t2 loaded
ReferenceError: loadJs is not defined

也就是说,t2.js中定义的函数没有访问loadJs函数,那么我想知道是否可以更改加载函数的运行时上下文,例如,当调用加载函数时:

fun && fun.apply(this);

是否可以在当前匿名函数的上下文下调用fun,然后fun可以访问所有定义的变量、函数,如loadJs等,而无需将其导出到window


我之所以对这种解决方案感兴趣,是因为我发现谷歌地图使用回调,例如,当使用谷歌地图v3时,以下脚本将加载到页面:

https://maps.gstatic.com/maps-api-v3/api/js/18/3/main.js

然后将加载另一个模块map

https://maps.gstatic.com/cat_js/maps-api-v3/api/js/18/3/{map}.js

当深入代码时,我发现{map}.js可以访问main.js中定义的变量。但我找不到魔法是如何发生的。

是否可以更改函数运行时范围…我想知道是否可以更改加载函数的运行时上下文,例如,当加载函数被调用时

没有。Javascript的作用域是词法上的,因此作用域完全取决于函数在代码中的创建位置,而不是从哪里调用函数或如何调用函数

> fun && fun.apply(this);

这将只设置函数执行上下文的一个参数,即this参数。

术语上下文普遍存在混淆。在ECMA-262(javascript基础语言的标准)中,上下文仅在执行上下文中使用,该上下文是函数内部的整个环境,并包括其this参数。

调用apply方法允许您指定函数的this的值,仅此而已,它们对执行上下文没有其他影响(这就是为什么this永远不应该被称为"上下文")。它们对标识符解析没有任何影响,标识符解析基于范围进行,无论this的值是多少,或者函数是从哪里调用的。

您可能会发现以下文章正在插入:标识符解析、执行上下文和范围链

您可以将其设置为全局。既然你已经有window.__jsload了,你可以把它附在那里。

__jsload.loadJs = loadJs;
 // // access like this  :
 // console.info(__jsload.loadJS);

或者,当您从__jsload调用它时,您可以将它传递给回调。

__jsload('t2', function (loadJs) {
   console.info("t2 loaded");
   console.info(loadJs);
}