JavaScript에서는 코드, 함수 또는 모듈 블록이 변수의 범위를 만듭니다. 예를 들어, if
코드 블록은 message
변수에 대한 범위를 생성합니다. if
代码块为变量 message
创建作用域:
if (true) { const message = 'Hello'; console.log(message); // 'Hello' } console.log(message); // throws ReferenceError
在 if
代码块作用域内可以访问 message
。但是在作用域之外,该变量不可访问。
好的,这是作用域的简短介绍。如果你想了解更多信息,建议阅读我的文章用简单的词解释 JavaScript 作用域。
以下是 5 种有趣的情况,其中 JavaScript 作用域的行为与你预期的不同。你可能会研究这些案例以提高对作用域的了解,或者只是为面试做准备。
1. for 循环内的 var 变量
思考以下代码片段:
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); // ???
当你打印 l
和 i
变量时会发生什么?
答案
console.log(l)
输出数字 3
,而 console.log(i)
则抛出 ReferenceError
。
l
变量是使用 var
语句声明的。你可能已经知道,var
变量仅受函数体作用域限制而并非代码块。
相反,变量 i
使用 let
语句声明。因为 let
变量是块作用域的,所以 i
仅在 for
循环作用域内才可访问。
修复
把 l
声明从 var l = colors.length
改为 const l = colors.length
。现在变量 l
被封装在 for
循环体内。
2. 代码块中的函数声明
在以下代码段中:
// ES2015 env { function hello() { return 'Hello!'; } } hello(); // ???
调用 hello()
会怎样? (代码段在 ES2015 环境中执行)
答案
因为代码块为函数声明创建了作用域,所以在 ES2015 环境中调用 hello()
会引发 ReferenceError: hello is not defined
。
有趣的是,在 ES2015 之前的环境中,在执行上述代码段时不会抛出错误。 你知道为什么吗?请在下面的评论中写下你的答案!
3. 你可以在哪里导入模块?
你可以在代码块中导入模块吗?
if (true) { import { myFunc } from 'myModule'; // ??? myFunc(); }
答案
上面的脚本将触发错误: 'import' and 'export' may only appear at the top-level
。
你只能在模块文件的最顶级作用域(也称为模块作用域)中导入模块。
修复
始终从模块作用域导入模块。另外一个好的做法是将 import
语句放在源文件的开头:
import { myFunc } from 'myModule'; if (true) { myFunc(); }
ES2015 的模块系统是静态的。通过分析 JavaScript 源代码而不是执行代码来确定模块的依赖关系。所以在代码块或函数中不能包含 import
语句,因为它们是在运行时执行的。
4. 函数参数作用域
思考以下函数:
let p = 1; function myFunc(p = p + 1) { return p; } myFunc(); // ???
调用 myFunc()
会发生什么?
答案
当调用函数 myFunc()
时,将会引发错误: ReferenceError: Cannot access 'p' before initialization
。
发生这种情况是因为函数的参数具有自己的作用域(与函数作用域分开)。参数 p = p + 1
等效于 let p = p + 1
。
让我们仔细看看 p = p + 1
。
首先,定义变量 p
。然后 JavaScript 尝试评估默认值表达式 p + 1
,但此时绑定 p
已经创建但尚未初始化(不能访问外部作用域的变量 let p = 1
)。因此抛出一个错误,即在初始化之前访问了 p
。
修复
为了解决这个问题,你可以重命名变量 let p = 1
,也可以重命名功能参数 p = p + 1
。
让我们选择重命名函数参数:
let p = 1; function myFunc(q = p + 1) { return q; } myFunc(); // => 2
函数参数从 p
重命名为 q
。当调用 myFunc()
时,未指定参数,因此将参数 q
初始化为默认值 p + 1
。为了评估 p +1
,访问外部作用域的变量 p
:p +1 = 1 + 1 = 2
if (true) { function greet() { // function body } class Greeter { // class body } } greet(); // ??? new Greeter(); // ???
message
는 범위 내에서 액세스할 수 있습니다. if
코드 블록 >. 하지만 범위 밖에서는 변수에 액세스할 수 없습니다. 🎜🎜알겠습니다. 스코프에 대한 간략한 소개입니다. 더 알고 싶다면 JavaScript의 역할을 간단한 단어로 설명하는 기사를 읽어 보시기 바랍니다. 도메인. 🎜🎜다음은 JavaScript 범위가 예상과 다르게 동작하는 5가지 흥미로운 상황입니다. 범위에 대한 이해를 향상시키거나 단순히 인터뷰를 준비하기 위해 이러한 사례를 연구할 수 있습니다. 🎜1. for 루프의 var 변수
🎜 다음 코드 조각: 🎜rrreee🎜l
및 i
변수를 인쇄하면 어떻게 되나요? 🎜답변
🎜console.log(l)
은 3
숫자를 출력하는 반면 console.log(i )
는 ReferenceError
를 발생시킵니다. 🎜🎜l
변수는 var
문을 사용하여 선언됩니다. 이미 알고 계시겠지만 var
변수 코드 블록이 아닌 함수 본문의 범위에 의해서만 제한됩니다. 🎜🎜대신 let
문을 사용하여 변수 i
가 선언됩니다. let
변수는 블록 범위이므로 i
는 for
루프 범위 내에서만 액세스할 수 있습니다. 🎜수정됨
🎜l
선언이 var l = colors.length
에서 const l = colors 로 변경되었습니다. 길이
. 이제 변수 l
가 for
루프 본문에 포함됩니다. 🎜2. 코드 블록의 함수 선언
🎜다음 코드 부분에서: 🎜rrreee🎜hello() 호출 / 코드> 어떻게 되나요? <em>(코드 조각은 ES2015 환경에서 실행됩니다.)</em>🎜<h4 id="strong-답변-strong"><strong>답변</strong></h4>🎜코드 블록이 함수 선언에 대한 범위를 생성하기 때문에 호출됩니다. ES2015 환경에서 <code>hello()
는 ReferenceError: hello가 정의되지 않았습니다
를 발생시킵니다. 🎜🎜흥미롭게도 ES2015 이전 환경에서는 위 코드 조각을 실행할 때 오류가 발생하지 않습니다. 이유를 아시나요? 아래 댓글에 답을 적어주세요! 🎜3. 모듈은 어디에서 가져올 수 있나요?
🎜코드 블록에서 모듈을 가져올 수 있나요? 🎜rrreee답변
🎜위 스크립트는 오류를 발생시킵니다:'가져오기' 및 '내보내기'는 최상위 수준에만 나타날 수 있습니다
. 🎜🎜이 작업은 모듈 파일의 최상위 범위에서만 수행할 수 있습니다(모듈 범위). 🎜수정
🎜항상 모듈 범위에서 모듈을 가져오세요. 또 다른 좋은 방법은import
문을 소스 파일 시작 부분에 배치하는 것입니다. 🎜rrreee🎜ES2015의 모듈 시스템은 정적입니다. 코드를 실행하는 대신 JavaScript 소스 코드를 분석하여 모듈 종속성을 확인합니다. 따라서 import
문은 런타임에 실행되기 때문에 코드 블록이나 함수에 포함할 수 없습니다. 🎜4. 함수 매개변수 범위
🎜다음 함수를 생각해 보세요. 🎜rrreee🎜myFunc()
호출 무슨 일이 일어났나요? 🎜답변
🎜myFunc()
함수를 호출하면 오류가 발생합니다: ReferenceError: 초기화 전에 'p'에 액세스할 수 없습니다. . 🎜🎜이는 함수의 매개변수가 자체 범위(함수 범위와 별개)를 갖기 때문에 발생합니다. <code>p = p + 1
매개변수는 let p = p + 1
과 동일합니다. 🎜🎜 p = p + 1
을 자세히 살펴보겠습니다. 🎜🎜먼저 p
변수를 정의합니다. 그런 다음 JavaScript는 기본 값 표현식 p + 1
을 평가하려고 시도하지만 이 시점에서 바인딩 p
가 생성되었지만 아직 초기화되지 않았습니다(외부 범위 p = 1로 설정). 따라서 초기화 전에 p
에 액세스했다는 오류가 발생합니다. 🎜수정
🎜이 문제를 해결하려면 변수let p = 1
의 이름을 바꾸거나 함수 매개변수 p의 이름을 바꿀 수 있습니다. = p + 1
. 🎜🎜함수 매개변수의 이름을 바꾸도록 선택하겠습니다. 🎜rrreee🎜함수 매개변수의 이름이 p
에서 q
로 바뀌었습니다. myFunc()
가 호출되면 매개변수가 지정되지 않으므로 q
매개변수가 기본값 p + 1
로 초기화됩니다. p +1
을 평가하려면 외부 범위의 p
변수(p +1 = 1 + 1 = 2
)에 액세스하세요. 🎜5. 函数声明与类声明
以下代码在代码块内定义了一个函数和一个类:
if (true) { function greet() { // function body } class Greeter { // class body } } greet(); // ??? new Greeter(); // ???
是否可以在块作用域之外访问 greet
和 Greeter
? (考虑 ES2015 环境)
答案
function
和 class
声明都是块作用域的。所以在代码块作用域外调用函数 greet()
和构造函数 new Greeter()
就会抛出 ReferenceError
。
6. 总结
必须注意 var
变量,因为它们是函数作用域的,即使是在代码块中定义的。
由于 ES2015 模块系统是静态的,因此你必须在模块作用域内使用 import
语法(以及 export
)。
函数参数具有其作用域。设置默认参数值时,请确保默认表达式内的变量已经用值初始化。
在 ES2015 运行时环境中,函数和类声明是块作用域的。但是在 ES2015 之前的环境中,函数声明仅在函数作用域内。
希望这些陷阱能够帮你巩固作用域知识!
英文原文地址:https://dmitripavlutin.com/javascript-scope-gotchas/
作者:Dmitri Pavlutin
更多编程相关知识,请访问:编程入门!!
위 내용은 JS 범위에 관한 5가지 함정(요약)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

JavaScript는 현대 웹 개발의 핵심 언어이며 다양성과 유연성에 널리 사용됩니다. 1) 프론트 엔드 개발 : DOM 운영 및 최신 프레임 워크 (예 : React, Vue.js, Angular)를 통해 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축합니다. 2) 서버 측 개발 : Node.js는 비 차단 I/O 모델을 사용하여 높은 동시성 및 실시간 응용 프로그램을 처리합니다. 3) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)
