앞에 쓴 글: javascript컬럼입니다. 주로 프레임워크가 만연한 시대에 시리즈를 시작하려고 합니다. 비록 직장에서는 인터뷰나 기술적인 진행을 위해 프레임워크를 사용하지만요. 이 단계에서는 JS 기본 지식의 기초가 금상첨화이며 반드시 배워야 하는 지식이기도 합니다. 자동차를 운전하는 사람들은 자동차에 대해 많이 알 필요는 없지만 공통적인 지식만 익히면 됩니다. 자동차의 기능. 하지만 자동차를 안다면 운전을 더 잘할 수 있습니다. 물론, 기사는 단지 하나의 지식 포인트에 대해서만 이야기하는 것이 아닙니다. 일반적으로 관련된 지식 포인트가 시리즈로 연결되어 자신의 학습을 기록하면서 자신의 학습을 공유하고 서로 격려하게 됩니다! 가능하시다면 저에게도좋아요 부탁드려요 여러분의 좋아요 덕분에 저도 업데이트를 더 열심히 할 수 있을 것 같아요!
먼저 한 줄의 코드를 살펴보겠습니다
var name='jack';复制代码
우리 눈에는 한 줄의 코드와 한 개의 문장으로 할 수 있는 일이지만, JS의 눈에는 코드가 있습니다. 제시된
var name; //编译阶段处理name='jack'; //执行阶段处理复制代码
는 원래 알고 있던 JS와 동일하지 않습니다. 왜냐하면 JS 컴파일은 주로 컴파일 단계와 실행 단계의 두 단계로 나누어지기 때문입니다. 두 단계.
이 단계의 주인공은 소위 컴파일러입니다. 이 컴파일러는 현재 범위를 검색하여 이름
. 이미 존재하는 경우 아무것도 하지 않고 무시합니다.var name
, 계속 컴파일하고, 그렇지 않은 경우 현재 범위에 name
변수입니다. 그런 다음 컴파일러는 엔진 실행에 필요한 코드를 생성하고 프로그램은 실행 단계에 들어갑니다name
的变量。如果已经存在,那么就什么都不做,直接忽略 var name
这个声明,继续编译下去;如果没有,则在当前作用域里新增一个叫 name
的变量。然后,编译器会为引擎生成运行时所需要的代码,程序就进入了执行阶段
这个阶段的主角就是大家所熟悉的JS引擎啦,JS引擎在运行的时候,也会先找遍当前作用域,看看是否有一个叫 name
name
의 변수가 있으면 딱 맞고, 없으면 바로 할당할 수 있다는 뜻입니다. 현재 범위에 존재하지 않는 경우 어떻게 해야 합니까? 그런 다음 머리를 내밀고 외부(상위 범위)를 살펴보고 그렇지 않은 경우 레이어별로 다시 검색하십시오(물론 존재하는 경우). 는 부모 레이어입니다). 그래도 결국 찾지 못한다면 JS 엔진은 아무 것도 할 수 없다는 것을 보여줄 것입니다. 그러니 그냥 예외를 던지고 다른 사람들에게 보여주면서 열심히 노력했다는 것을 보여주세요. 🎜🎜위에서 언급했듯이 현재 범위에서 상위 범위, 상위 범위까지 외부에서 레이어별로 검색하는 것이 소위 범위 체인과 마찬가지로 각 링크가 올라갑니다. 하나씩 설명이 너무 적절하지 않나요? 요약하면 🎜스코프는 스코프 내에 중첩되며 소위 스코프 체인🎜🎜이 있습니다.大家都知道,变量最基本的能力就是能够存储变量当中的值、并且允许我们对这个变量的值进行访问和修改,而对于变量存储,访问的一套规则,就是所谓的作用域
在任何函数外或者代码块之外的顶层作用域就是全局作用域,而里面的变量就是全局变量
var name='jack'; //全局作用域function showName(){ //函数作用域 console.log(name);}{ name='test'; //块级作用域}showName(); //test复制代码
可以看到全局变量,无论是在全局作用域,函数作用,还是块级作用域中都可以正常访问
在函数内的作用域就是函数作用域
function showName(){ var name='jack'; //函数作用域}showName(); //方法调用{ console.log(name); //块级作用域,Uncaught ReferenceError: name is not defined}console.log(name); //全局作用域,Uncaught ReferenceError: name is not defined复制代码
可以看到函数内部变量,在全局作用域以及块级作用域中,都无法访问,只有在函数内部,才能访问的到,所以函数内的变量也被称为局部变量
在 ES6
中新出的两个新关键字 let
和 const
中,自带块级作用域,块级作用域相当于是只在这块代码块中生效,如果它被大括号 {}
所包围,那么大括号中就是一段代码块,代码块中使用 let
和 const
声明的变量也被称为局部变量
{ let name='jack'; } console.log(name); //Uncaught ReferenceError: name is not defined function showName{ console.log(name); } showName(); //Uncaught ReferenceError: name is not defined复制代码
可以看到块级作用域中的变量,出了那个代码块,就找不到了
其实上面的三种情况,结合JS编译原理和作用域链向外不向内查找,思考一下,也不难理解
回到作用域链,其实在上面已经解释的差不多了,作用域和作用域的嵌套,就产生了作用域链,另外要记住的一个特性就是作用域链的查找,向外不向内,想想探出头去,而不是看着锅里,就可以了
先来看一段代码
name='jack';console.log(name); //jackvar name;复制代码
你会发现,这段代码不会发生报错,并且能正常地运行,结合上面所说的JS编译原理,你就能想到,在JS的眼中,它的代码实际上是这样子的,这就是所谓的变量提升,说白了那就是代码的声明提到代码的最前面
var name;name='jack';console.log(name); //jack复制代码
其实这个变量提升应该是照道理接着编译原理写下来的,为什么放到了最后呢,因为如果你忘了,正好往上翻一下,重新回温一遍JS编译原理
紧接着上面,让我们来看下不吃变量提升这一套的 let
和 const
,先来看一段代码
name='jack';console.log(name) //Uncaught ReferenceError: Cannot access 'name' before initializationlet name;复制代码
黑人问号 ??? ,说好的变量提升呢,记住 let
和 const
的一个特点,禁用变量提升,这也是 ES6
故意为之的,将生命前不可用做到了强约束,总结而言,** var
存在变量提升, let
和 const
不存在变量提升**
既然已经提到了 const
,顺带提一下它声明了以后必须赋值的操作
const name; //Uncaught SyntaxError: Missing initializer in const declaration复制代码
紧接着上面,让我们来看下什么叫做暂时性死区,先来看一段代码
var name='jack';{ name='bob'; let name; //Uncaught ReferenceError: Cannot access 'name' before initialization}复制代码
记住 ES6
中的一个特性,如果区块中存在 let
和 const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。因为JS清楚地感知到了 name
是用 let
声明在当前这个代码块内的,所以会给这个变量 name
加上了暂时性死区的限制,它就不往外探出头了。
那么,如果我们把上面的let name;
去掉,程序也将正常运行, name
的值也被成功修改为了bob,就是正常地按照作用域链的规则,向外探出头去了。
更多相关免费学习推荐:javascript(视频)
위 내용은 JS 시리즈(1)의 컴파일 원리, 범위, 범위 체인, 변수 승격 및 임시 데드존을 한 논문에서 이해합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!