Javascript 阴影领域
这听起来黑暗而神秘——但它只是另一个未来的 Javascript 特性。ShadowRealm是 Javascript的一项新功能,它将让我们创建一个单独的全局上下文来执行 Javascript。在本文中,我们将了解什么是 ShadowRealm 及其工作原理。
在 Javascript 中支持 ShadowRealms#
ShadowRealm
s 是一个 Javascript 提案,目前处于第 3 阶段。因此,ShadowRealm
s 在浏览器或服务器端语言(如 Node.JS)中不支持,并且考虑到它多年来发生了许多变化,因此没有稳定的 babel 或 npm插件来填充功能。然而,鉴于它已经达到第 3 阶段,这意味着未来不会有太多变化,我们可以期待ShadowRealm
s 在未来的某个时候获得原生支持。
Javascript 中的 ShadowRealms 是如何工作的#
AShadowRealm
最终是一种使用不同的全局对象设置全新环境的方法,将代码与其他领域分开。当我们在 Javascript 中谈论全局对象时,我们指的是window
or的概念globalThis
。最终试图解决的问题是ShadowRealm
减少不同代码集之间的冲突,并为需要隔离运行的代码的执行和运行提供安全的环境。这意味着其他代码或包对全局对象的污染更少。因此,a 中的代码ShadowRealm
无法与不同领域中的对象进行交互。
ShadowRealm 用例:
- 代码编辑器,用户可以在其中编辑代码,我们不想与主网页进行交互。
- 可以独立执行的插件。
- 在单独的环境中模拟 DOM,即如果我们需要知道某些场景中的滚动位置,我们可以在 a 中模拟它,
ShadowRealm
这样用户在主网页上滚动就不会影响window.top
我们模拟中的变量。
ShadowRealm
它与所有其他 Javascript 在同一个线程上运行 – 所以如果你想多线程你的 Javascript,你仍然必须使用Web Workers。因此,aShadowRealm
可以存在于 worker 中,也可以存在于常规 Javascript 文件中。ShadowRealm
s 甚至可以存在于其他ShadowRealm
s 中。
在 Javascript 中创建 ShadowRealm#
让我们看看 aShadowRealm
在代码中的实际表现。我们要做的第一件事是调用一个新ShadowRealm
实例。然后我们可以将一些 Javascript 导入我们的领域,它将在其中运行。为此,我们使用一个名为 的函数importValue
,它的工作方式与 相同import
。
let myRealm = new ShadowRealm(); let myFunction = await myRealm.importValue('./function-script.js', 'analyseFiles'); // Now we can run our function within our ShadowRealm let fileAnalysis = myFunctions();
在上面的示例中,analyseFiles
是我们从function-script.js导入的导出名称。然后我们捕获此导出并将其存储在myFunction
. 重要的是,我们导入到我们领域的导出必须是可调用的,因此它必须是我们可以运行的有效函数。
我们的function-script.js文件只是一个带有导出的普通 Javascript 文件。它可能看起来像这样:
export function analyseFiles() { console.log('hello'); }
TheShadowRealm
与我们可能拥有的其他全局对象完全分开,例如window
or globalThis
。
与其他导入类似,我们可以使用大括号导入符号:
let myRealm = new ShadowRealm(); const { runFunction, testFunction, createFunction } = await myRealm.importValue('./function-script.js'); let fileAnalysis = runFunction();
importValue
或者,如果我们想使用命名的 s ,我们可以创建多个全部转换为数组的承诺。
let myRealm = new ShadowRealm(); const [ runFunction, testFunction, createFunction ] = await Promise.all([ myRealm.importValue('./file-one.js', 'runFunction'), myRealm.importValue('./file-two.js', 'testFunction'), myRealm.importValue('./file-three.js', 'createFunction'), ]); let fileAnalysis = runFunction();
在 ShadowRealms 中使用评估执行代码
如果我们想直接在 ShadowRealm 中执行代码,而不是来自另一个文件,我们可以使用evaluate
ShadowRealm 上的方法来执行一串 Javascript。这与以下工作方式大致相同eval()
:
let myRealm = new ShadowRealm(); myRealm.evaluate(`console.log('hello')`);
ShadowRealm importValue 是 thennable
由于importValue
返回一个承诺,它的价值是 thennable。这意味着我们可以使用then()
它,然后用它返回的输出函数做一些事情。例如:
window.myVariable = 'hello'; let myRealm = new ShadowRealm(); myRealm.importValue('someFile.js', 'createFunction').then((createFunction) => { // Do something with createFunction(); console.log(window.myVariable); // Returns undefined })
很酷的一点是全局对象不会泄漏到then()
语句中。所以window.myVariable
是未定义的。这为我们提供了一个完全隔离的代码区域,我们不必担心来自全局对象的干扰!
我们也可以使用这种方法来访问定义在someFile.js
. 例如,假设我们更改someFile.js
为:
globalThis.name = "fjolt"; export function returnGlobals(property) { return globalThis[property]; }
现在,在我们的then
函数中,我们可以获得以下值globalThis.name
:
window.myVariable = 'hello'; let myRealm = new ShadowRealm(); myRealm.importValue('someFile.js', 'returnGlobals').then((returnGlobals) => { // Do something with returnGlobals(); console.log(returnGlobals("name")); // Returns fjolt console.log(window.myVariable); // Returns undefined })
结论#
今天,iframe
s 是我们通常在 web 上分离出不同环境的方式。iframe
s 很笨重,使用起来会很烦人。ShadowRealm
另一方面,s 更高效,允许我们轻松地与我们现有的代码库集成,并与 Web Workers等现代 Javascript 技术很好地集成。
鉴于它们为代码执行提供一个独立区域的独特价值主张,它根本不与代码库的其余部分交互,ShadowRealm
s 很可能成为编写 Javascript 代码的主要工具。它们可能成为包和模块导出其内容的重要方式,而无需担心来自代码库其他部分的干扰。因此,期待看到它们在未来突然出现。