惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
O
OpenAI News
W
WeLiveSecurity
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
H
Heimdal Security Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
Cloudbric
Cloudbric
T
Threatpost
T
Troy Hunt's Blog
T
Tenable Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
The Hacker News
The Hacker News
Know Your Adversary
Know Your Adversary
Forbes - Security
Forbes - Security
Cyberwarzone
Cyberwarzone
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
腾讯CDC
博客园 - 三生石上(FineUI控件)
爱范儿
爱范儿
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
T
The Blog of Author Tim Ferriss
MongoDB | Blog
MongoDB | Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
D
Docker
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
I
InfoQ
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
A
Arctic Wolf
L
LINUX DO - 热门话题
The Cloudflare Blog
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件

Dmitri Pavlutin Blog

Pure Functions in JavaScript: A Beginner's Guide Record Type in TypeScript: A Quick Intro How to Write Comments in React: The Good, the Bad and the Ugly 4 Ways to Create an Enum in JavaScript React forwardRef(): How to Pass Refs to Child Components TypeScript Function Types: A Beginner's Guide How to Use v-model to Access Input Values in Vue Mastering Vue refs: From Zero to Hero Environment Variables in JavaScript: process.env 5 Must-Know Differences Between ref() and reactive() in Vue How to Destructure Props in Vue (Composition API) Triangulation in Test-Driven Development How to Use nextTick() in Vue Programming to Interface Vs to Implementation A Smarter JavaScript Mapper: array.flatMap() Array Grouping in JavaScript: Object.groupBy() How to Access ES Module Metadata using import.meta JSON Modules in JavaScript How to Trim Strings in JavaScript TypeScript Function Overloading How to Debounce and Throttle Callbacks in Vue How to Show/Hide Elements in Vue Sparse vs Dense Arrays in JavaScript How to Fill an Array with Initial Values in JavaScript Covariance and Contravariance in TypeScript What are Higher-Order Functions in JavaScript? How to Use TypeScript with React Components Index Signatures in TypeScript How to Use React useReducer() Hook unknown vs any in TypeScript A Guide to React Context and useContext() Hook How to Use Promise.any() 2 Ways to Remove a Property from an Object in JavaScript 'return await promise' vs 'return promise' in JavaScript How to Use Promise.allSettled() How to Use fetch() with JSON JavaScript Promises: then(f,f) vs then(f).catch(f) What is a Promise in JavaScript? How to Use Promise.all() A Simple Guide to Component Props in React Don't Stop Me Now: How to Use React useTransition() hook A Simple Explanation of JavaScript Variables: const, let, var ES Modules Dynamic Import How to Memoize with React.useMemo() How to Cleanup Async Effects in React Why Math.max() Without Arguments Returns -Infinity How to Debounce and Throttle Callbacks in React Don't Confuse Function Expressions and Function Declarations in JavaScript How to Use ES Modules in Node.js Solving a Mystery Behavior of parseInt() in JavaScript How to Use Array Reduce Method in JavaScript 3 Ways to Merge Arrays in JavaScript A Guide to Jotai: the Minimalist React State Management Library The Difference Between Values and References in JavaScript How to Implement a Queue in JavaScript A Helpful Algorithm to Determine "this" value in JavaScript React useRef() Hook Explained in 3 Steps 7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them? How to Greatly Enhance fetch() with the Decorator Pattern 7 Interview Questions on JavaScript Closures. Can You Answer Them? What's a Method in JavaScript? array.sort() Does Not Simply Sort Numbers in JavaScript How to Solve the Infinite Loop of React.useEffect() The New Array Method You'll Enjoy: array.at(index) What's the Difference between DOM Node and Element? Why Promises Are Faster Than setTimeout()? Everything About Callback Functions in JavaScript How React Updates State 5 Mistakes to Avoid When Using React Hooks 5 Best Practices to Write Quality JavaScript Variables Type checking in JavaScript: typeof and instanceof operators 3 Ways to Check if a Variable is Defined in JavaScript React Forms Tutorial: Access Input Values, Validate, Submit Forms Prototypal Inheritance in JavaScript How to Timeout a fetch() Request How to Learn JavaScript If You're a Beginner A Simple Explanation of React.useEffect() A Simple Explanation of JavaScript Iterators How to Use React Controlled Inputs Everything about null in JavaScript How to Use Fetch with async/await Getting Started with Arrow Functions in JavaScript An Interesting Explanation of async/await in JavaScript Front-end Architecture: Stable and Volatile Dependencies Is it Safe to Compare JavaScript Strings? How to Access Object's Keys, Values, and Entries in JavaScript What Actually is a String in JavaScript? 3 Ways to Shallow Clone Objects in JavaScript (w/ bonuses) Checking if an Array Contains a Value in JavaScript JavaScript Event Delegation: A Beginner's Guide How to Parse URL in JavaScript: hostname, pathname, query, hash 3 Ways to Detect an Array in JavaScript How to Get the Screen, Window, and Web Page Sizes in JavaScript 3 Ways to Check If an Object Has a Property/Key in JavaScript How to Compare Objects in JavaScript Object.is() vs Strict Equality Operator in JavaScript Own and Inherited Properties in JavaScript 5 Differences Between Arrow and Regular Functions How to Use Object Destructuring in JavaScript Your Guide to React.useCallback()
5 JavaScript Scope Gotchas
Dmitri Pavlutin · 2020-04-27 · via Dmitri Pavlutin Blog

In JavaScript, a code block, a function, or module create scopes for variables. For example, the if code block creates a scope for the variable message:


if (true) {

const message = 'Hello';

console.log(message); // 'Hello'

}

console.log(message); // throws ReferenceError


message is accessible inside the scope of if code block. However, outside of the scope, the variable is not accessible.

Ok, that was a short intro to scopes. If you'd like to learn more, I recommend reading my post JavaScript Scope Explained in Simple Words .

What follows are 5 interesting cases when the JavaScript scope behaves differently than you expect. You might study these cases to improve your knowledge of scopes, or just to prepare for a fancy coding interview.

1. var variables inside for cycle

Consider the following code snippet:


const colors = ['red', 'blue', 'white'];

for (let i = 0, var l = colors.length; i < l; i++) {

console.log(colors[i]); // 'red', 'blue', 'white'

}

console.log(l); // ???

console.log(i); // ???


What happens when you log l and i variables?

The answer

console.log(l) logs the number 3, while console.log(i) throws a ReferenceError.

The l variable is declared using a var statement. As you might know already, var variables are scoped only by a function body and not by a code block.

On the opposite, the variable i is declared using a let statement. Because let variables are block scoped, i is accessible only within the scope of for cycle.

The fix

Change l declaration from var l = colors.length to const l = colors.length. Now the variable l is encapsuled inside for cycle body.

2. function declaration inside code blocks

In the following code snipped:


// ES2015 env

{

function hello() {

return 'Hello!';

}

}

hello(); // ???


What happens when you invoke hello()? (consider the snippet is executed in ES2015 environment)

The answer

Because the code block creates a scope for the function declaration, invoking hello() (in ES2015 environment) throws ReferenceError: hello is not defined.

Interestingly that in a pre-ES2015 environment executing the above code snippet works without throwing errors. Do you know why? If so, please write your answer in a comment below!

3. Where can you import a module?

Can you import a module inside a code block?


if (true) {

import { myFunc } from 'myModule'; // ???

myFunc();

}


The answer

The script above would trigger an error: 'import' and 'export' may only appear at the top-level.

You can import a module only at the topmost scope of the module file, also named the module scope.

The fix

Always import modules from the module scope. Plus a good practice is to place the import statements at the beginning of the source file:


import { myFunc } from 'myModule';

if (true) {

myFunc();

}


ES2015 modules system is static. The modules dependencies are determined by analyzing the JavaScript source code, without executing it. Thus you cannot have import statements inside code blocks or functions since they are executed during runtime.

4. Function parameters scope

Consider the following function:


let p = 1;

function myFunc(p = p + 1) {

return p;

}

myFunc(); // ???


What happens when myFunc() is invoked?

The answer

When the function is invoked myFunc(), an error is thrown: ReferenceError: Cannot access 'p' before initialization.

It happens because the function parameters have their own scope (separated from the function scope). The parameter p = p + 1 is equivalent to let p = p + 1.

Let's take a closer look at p = p + 1.

First, a variable p is defined. Then JavaScript tries to evaluate the default value expression p + 1, but the binding p is already created but not yet initialized (the variable let p = 1 of the outer scope is not accessed). Thus an error is thrown that p is accessed before initialization.

The fix

To fix the problem, you can either rename the variable let p = 1, or rename the function parameter p = p + 1.

Let's choose to rename the function parameter:


let p = 1;

function myFunc(q = p + 1) {

return q;

}

myFunc(); // => 2


The function parameter was renamed from p to q. When the invocation happens myFunc(), the argument is not specified, thus the parameter q is initialized with a default value p + 1. To evaluate p + 1, the variable p of the outer scope is accessed: p + 1 = 1 + 1 = 2.

5. Function declaration vs class declaration

The following code defines a function and a class inside of a code block:


if (true) {

function greet() {

// function body

}

class Greeter {

// class body

}

}

greet(); // ???

new Greeter(); // ???


Are both greet and Greeter accessible outside of the block scope? (consider ES2015 environment)

The answer

Both function and class declarations are block scoped. So invoking the function greet() and constructor new Greeter() outside of if code block scope throw a ReferenceError.

6. Summary

Care must be taken with var variables because they are function scoped, even being defined inside a code block.

Because the ES2015 modules system is static, you have to use the import syntax (as well as export) at the module scope.

The function parameters have their scope. When setting up a default parameter value, be sure that the variables inside the default expression are initialized with values.

In an ES2015 runtime environment, the function and class declarations are block scoped. However, a pre-ES2015 env, the function declarations are only function scoped.

Hopefully, these gotchas have helped you solidify your scope knowledge!

What other scope gotchas have you encountered?