JavaScript范围的简单理解[译]

date
Apr 29, 2021
slug
a-simple-explanation-of-javascript-scope
status
Published
tags
Website
summary
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
type
Post
 
[TOC]
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。

Global scope

<!--more-->
顾名思义,可以从任何内部范围(最外部的范围)访问此范围。
//app.js
const settings = {...};

//settings can be used in any other scope inside your app

Block 作用域

JavaScript中的代码块(例如 if condition,loop 等)定义了自己的作用域,但前提是你使用的ES6引入的**let** 和 const 变量。
if(true){
let blog = 'hashnode';
console.log(blog); // 'hashnode'

var state = 'awesome';
console.log(state); // 'awesome'
}
console.log(blog); // Reference Error
console.log(state); // 'awesome'
blog 是在 if block 作用域中定义的,并且只能在其中访问,与var的区别在于: var声明的不是块级作用域(它是函数/模块作用域的,在后面的内容有更多的介绍)

Function 作用域

与块作用域不同,函数作用域将保存所有三个(varlet , const)变量声明。
function writeBlogPost(){
const postID = 113312;
let postMeta = 'very important meta data';
var postTitle = 'A Simple Explanation of JavaScript Scope';

console.log(postID); // 113312
console.log(postMeta); // 'very important meta data'
console.log(postTitle); // 'A Simple Explanation of JavaScript Scope'
}
writeBlogPost();

console.log(postID);  // Reference Error
console.log(postMeta);  // Reference Error
console.log(postTitle); // Reference Error
与函数主体 创建varletconst 的作用域相同,它也为函数声明创建作用域。
function writeBlogPost(){
//..
   function checkSpelling(){ ... }
   console.log(checkSpelling()); // some output
}

console.log(checkSpelling()); // Reference Error
现在让我们看看如何在嵌套函数中共享变量。

Lexical 作用域

这个是词法范围作用域, 让我们从两个函数开始。
function writeBlogPost(){
   // outer scope
   let postTitle = 'A Simple Explanation of JavaScript Scope';
   console.log(status); //   Reference Error

   function checkSpelling(){
     // inner scope
    let status = 'ok';
    console.log(postTitle); // A Simple Explanation of JavaScript Scope';
   }

   return checkSpelling;

}

var write = writeBlogPost();
write();
从代码上看,我们可以从内部函数checkSpelling可以看到外部函数writeBlogPostpostTitle变量,但实际上并非如此,外部函数writeBlogPost不能看到内部函数checkSpellingstatus变量。
为什么会出现这样的呢? 我能想到的最简单参考是参考单面镜,你只能从一名看。
如果我们有多个作用域/函数,它会像这样分层
//mirror direction
--->
最内部Function -> 内部Function -> 最外部函数Function -> 全局
但是,这还不是全部,如果再看一遍我们的函数,您会发现外部函数返回的是checkSpelling,这实际上意味着函数“完成了”,并且变量的作用域和它们的数据应该消失了吗?是的,您是对的,这就是***Closures***可以找到其用途的地方。
MDN "definition"
“A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.”

Module scope

让我们创建一个简单的模块 blogData
const userID = 93939;

/*some operations with user id...*/
现在,让我们尝试导入这个模块并使用 userID
import './blogData';

console.log(userID) // Reference Error
这是怎么回事呢? userIDblogData模块之外无法访问(除非使用export 显式导出)。
模块的作用域能够使模块被封装,因此每个私有变量(未导出的变量)都包留有内部细节,模块作用域可以防止外部变量访问这些变量。

Variable isolation

变量隔离,这是真正的保护程序,使我们可以重用常见的变量名。
简而言之,就像我之前写的那样,letconst是块作用域的意思是我们可以使用相同的变量名而不会发生冲突,这就是它的样子:
function getBlogHearts(){
let count = 10;
console.log(count) // 10
}

function getBlogViews(){
let count = 55;
console.log(count) // 55
}
两者都有count变量,我们可以毫无问题地使用它。

总结

  • 作用域是管理变量可用性的策略,在作用域中定义的变量只能在该作用域中访问。
  • 作用域由代码块(code blocks)、函数(functions )和模块(modules)创建。
  • 作用域可以嵌套,内部函数可以访问外部函数数据/变量。
  • constlet由代码块定义,而var仅由函数和模块定义。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。
JavaScript中的作用域是处理变量可用性的重要概念。如果要用JavaScript编写代码,必须理解作用域。
我们将使用简单的例子一步一步的介绍,下面是你将要学习的内容。

Nobelium is built with ♥ and ⚛ Next.js. Powered by

© kelvin 2021