> For the complete documentation index, see [llms.txt](https://docs.wem.io/platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.wem.io/platform/tutorials/building-widgets/wemscript/9-script-blocks-global-scope.md).

# 9. Script Block - Global Scope

In the previous chapter, we were introduced to the specific types of script blocks and when to use them. Within these blocks, we use `window[Symbol.for(<?js OutputId() ?>)]` to assign it to the instance of the Note widget. But what is the purpose of this? Let's examine what is happening under the hood to understand it better.

Let’s take the following widget as an example and see how the final rendered page output will look:

```html
<h2>Script Block Example Widget</h2>
<script>
	console.log("Regular JavaScript script block");
</script>
<? scriptmodule "script-block-example-widget" ?>
	console.log("Script module");
<? end ?>
<? scriptreference "example-website-script" "https://example.website/script.js" ?>
<? startupscript ?>
	console.log("Startup script");
<? end ?>
<? submitscript ?>
	console.log("Submit script");
<? end ?>
<? unloadscript ?>
	console.log("Unload script");
<? end ?>
```

When inspecting the code output of the page and observing how this widget has been rendered, it roughly translates to the following stripped-down output:

```html
<html>
	<head>
		...
		<script>
			console.log("Script module");
		</script>
		<script src="https://example.website/script.js"></script>
		...
	</head>
	<body>
		...
		<!-- Page content -->
		...
		<h2>Script Block Example Widget</h2>
		<script>
			console.log("Regular JavaScript script block");
		</script>
		...
		<!-- Other page content -->
		...
		<script> 
			Runtime.scripts.addStartupScript(function() {
				console.log("Startup script");
			});
			
			Runtime.scripts.addSubmitScript(function() {
				console.log("Submit script");
			});
			
			Runtime.scripts.addUnloadScript(function() {
				console.log("Unload script");
			});
		</script>
	</body>
</html>
```

A few interesting things are happening here. The `scriptmodule` is JavaScript code inside a `<script>` tag that has been added to the `<head>` section. The `scriptreference` behaves similarly. The regular `<script>` blocks are rendered as part of the page body content. However, you will notice that the code inside the other script blocks is registered at the end of the `<body>` in anonymous functions.

It is therefore crucial that your function and class names are unique when used in a `scriptmodule` or `scriptreference`. To clarify, consider these two widgets created by Bob and Jane:

```html
<? scriptmodule "bobs-button" ?>
	class Button {/* Bob's button */}
<? end ?>
```

```html
<? scriptmodule "janes-button" ?>
	class Button {/* Jane's button */}
<? end ?>
```

This will output roughly to:

```html
<head>
	<script>
		class Button {/* Bob's button */}
	</script>
	<script>
		class Button {/* Jane's button */}
	</script>
</head>
```

In this case, Bob's button is overwritten by Jane's, which is problematic. The `scriptreference` faces the same issue, as the script is loaded externally instead of being embedded within the page itself.

We resolved this issue in the Note widget by using `class WemAcademyNote` instead of `class Note`. While this is not a perfect solution, it helps minimize naming collisions.

There are other ways to address this naming collision, but they come with trade-offs. I will explain those later. First, let’s take a closer look at `window[Symbol.for(<?js OutputId() ?>)]`. Notice that the `startupscript`, `submitscript`, and `unloadscript` are anonymous functions. But what if we need access to context outside their local scope? This was the problem we encountered in the Note widget. To achieve this, we need a way to share state between those functions, which requires a global context. However, this can be very risky if not handled carefully.

Let's examine a stripped-down version of initializing and disposing of the Note widget from the previous chapter in a potentially dangerous way:

```html
<? startupscript ?>
	const note = new Note();
	document.documentElement.append(note.rootEl);
	window.note = note;
<? end ?>
<? unloadscript ?>
	window.note.dispose();
<? end ?>
```

This will output roughly to:

```html
<body>
	...
	<script> 
		Runtime.scripts.addStartupScript(function() {
			const note = new Note();
			document.documentElement.append(note.rootEl);
			window.note = note;
		});
		
		Runtime.scripts.addUnloadScript(function() {
			window.note.dispose();
		});
	</script>
</body>
```

In this example, we declared a global variable `note`, which can be risky. If another piece of JavaScript code uses a global variable with the same name, we may encounter undefined behavior. In this case, we could inadvertently overwrite someone else's `note` variable. This is a classic pitfall of using global variables!

However, there is a way to make this global variable "hidden." Let's dissect `window[Symbol.for(<?js OutputId() ?>)]` using the following code:

```html
<? startupscript ?>
	const note = new Note();
	document.documentElement.append(note.rootEl);
	window[Symbol.for(<?js OutputId() ?>)] = note;
<? end ?>
<? unloadscript ?>
	window[Symbol.for(<?js OutputId() ?>)].dispose();
<? end ?>
```

This will output to the following:

```html
<body>
	...
	<script> 
		Runtime.scripts.addStartupScript(function() {
			const note = new Note();
			document.documentElement.append(note.rootEl);
			window[Symbol.for("cc1")] = note;
		});
		
		Runtime.scripts.addUnloadScript(function() {
			window[Symbol.for("cc1")].dispose();
		});
	</script>
</body>
```

Here, we see that `<? OutputId() ?>` has printed `"cc1"`. As we learned in previous chapters, `OutputId()` creates a unique identifier for each instance of the widget on the page. This means that if we add multiple instances of this widget, the identifiers will be `"cc2"`, `"cc3"`, and so on. Note that we use `"cc1"` as an example, and it is bound to the implementation of the WEM Runtime, so it can be anything.

The `window` object is the global object in JavaScript, and the `Symbol` class is particularly interesting here. It creates symbols that are guaranteed to be unique. In our case, we use it to create a unique key that we store in `window`, effectively creating our "hidden" global variable. In other words, this approach provides a form of weak encapsulation or weak information hiding.

You might wonder, "What if we navigate to the next page? Wouldn't we potentially have another instance of a widget called `cc1`?" Yes, that is true, but it does not matter because we disposed of the instance of the note in the previous `unloadscript`. Therefore, it is acceptable to overwrite the contents of `window[Symbol.for("cc1")]`.

In our Note widget, we implemented the following:

```html
<? unloadscript ?>
	const noteSymbol = Symbol.for(<?js OutputId() ?>);
	window[noteSymbol].dispose();
	delete window[noteSymbol];
<? end ?>
```

To ensure that we clean everything up, we also `delete` our "hidden" global variable, as shown above. This helps the JavaScript garbage collector free up memory space. More importantly, it ensures that we do not have access to the variable after it has been used.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wem.io/platform/tutorials/building-widgets/wemscript/9-script-blocks-global-scope.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
