目录
除了自执行函数IIFE(隔绝外部作用域),箭头函数(无function)
let 、const、calss :声明不赋值,暂时性死区访问
strict严格模式:不允许无var声明,不允许挂载window,this为undefined
函数作用域:(有无var、let、const)局部变量,外部不可访问
自执行函数IIFE::特殊原因--IIFE 函数具备自己的作用域
分词/词法分析:分解(var a=2=> var,a,=,2)
解析/语法分析:词法数组=>程序语法 结构的“抽象语法树”(a->2)(Abstract Syntax Tree,AST)
声明 declare(值默认undefined):声明存在
定义 defined(赋值操作)
当栈内存作用域形成时,JS执行前,声明[,赋值]提升到代码块的顶部
console.log(a)//undefined
if(false){
var a = 'a'
}
声明前访问
不报错
function:
声明+赋值
除了自执行函数IIFE(隔绝外部作用域),箭头函数(无function)
var:
声明不赋值
报错
let
、const、calss
:声明不赋值,暂时性死区访问
不带var:无提升,is not defined
var a=b=1 等价于var a=1;b=1
变量重复声明
可重复声明
无var
function a(b){
console.log(b);
}
a(45);
// 等价于
function a(b){
b;
console.log(b);
}
a(45);
var、function:只提升一次
var a = 1;
function foo(a) {
console.log(a)
var a
console.log(a)
}
foo(a);
// 输出 1 1
不允许重复声明:let、const,SyntaxError
let x = 1;
{
var x = 2; // 重复声明的 SyntaxError
}
function和var重名/共用一个标识名
访问变量时机
var声明前:undefined
console.log(a);
var a=1;
function a(){
console.log(1);
}
// 或
console.log(a);
function a(){
console.log(1);
}
var a=1;
// 输出都是: ƒ a(){ console.log(1);}
var声明后:js用到变量时才赋值,可能覆盖
//1.getName 声明不赋值
var getName = function (){
console.log(4)
}
//2.getName=....log(5) 声明+赋值
function getName() {
console.log(5)
}
//3.getName=....log(4)var变量在使用到时赋值
getName()//4
var a=1;
function a(){
console.log(1);
}
console.log(a);
//或
function a(){
console.log(1);
}
var a=1;
console.log(a);
// 输出都是: 1
let
、const
、class:块级作用域
在类的方法中,this
关键字指向当前实例,而不是指向全局对象。
暂时性死区:作用域/使用起点~变量声明
“暂时性”区:这个区域取决于代码执行的时间点,而不是代码编写的顺序。
{
// 暂时性死区始于作用域开头
const func = () => console.log(letVar); //
// 在暂时性死区内访问 letVar 会抛出 `ReferenceError`
let letVar; // 暂时性死区结束(对 letVar 而言)
func(); // 在暂时性死区外调用,会输出 undefined
}
用 let
、const
或 class
声明的变量可以称其从代码块的开始一直到代码执行到变量声明的位置前,都处于一个“暂时性死区”(Temporal dead zone,TDZ)中。
当变量处于暂时性死区之中时,其尚未被初始化,并且任何访问其的尝试都将导致抛出 ReferenceError。
当代码执行到变量被声明的位置时,变量会被初始化为一个值。如果变量声明中未指定初始值,则变量将被初始化为 undefined
。
这与 var 声明的变量不同,如果在声明位置前访问 var
声明的变量会返回 undefined
。
{
// 暂时性死区始于作用域开头
console.log(bar); // undefined
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
var bar = 1;
let foo = 2; // 暂时性死区结束(对 foo 而言)
}
顶级作用域
挂载this实验时,一定要记得刷新环境,否则还挂在window上
MDN的浏览器环境,var不会挂载到this,但function,无var会挂载
function和有无var
浏览器环境:在全局对象window上创建属性
var a='a'
b='b'
function c(){}
console.log(this.a,this.b,this.c)//a b c(){}
包括块作用域{ }
if(true){
var a = 'a'
}
console.log(this.a)//a
不会在全局对象上创建属性:
node.js环境:全局对象global
Node.js 使用了 CommonJS 模块系统,每个模块都被封装在一个函数中,这样就避免了全局命名空间的污染。
Node.js 中的每个文件都被视为一个模块,每个模块都有其自己的作用域。
当你在 Node.js 模块中使用 var
声明变量时,该变量仅在该模块内部可见。
strict严格模式:不允许无var声明,不允许挂载window,this为undefined
"use strict";
console.log(this)//undefined
b='b'//b is not defined ,执行到此就会报错,不允许赋值
c //c is not defined ,执行到此就会报错
var a='a'
function fun(){}
console.log(this.a,window.fun)
// Cannot read properties of undefined (reading 'a')
// undefined
let
不会在全局对象this上创建属性
x = "无var";
let y = "let";
var z="var"
function fun(){}
console.log(this.fun); // ()=>{}
console.log(this.x); // 无var
console.log(this.y); // undefined
console.log(this.z); // undefined(受限浏览器环境,如MDN)/var(正常浏览器环境,如菜鸟教程)
函数作用域:(有无var、let、const)局部变量,外部不可访问
function fun(){
x = "无var";
let y = "let";
var z="var"
}
console.log(x); // x is not defined
console.log(y); // y is not defined
console.log(z); // z is not defined
console.log(this.x); // undefined
console.log(this.y); // undefined
console.log(this.z); // undefined
内部作用域优先级高于外部作用域
// 1
console.log(a,b)//undefined; b is not defined
var a =12,b ='林一一'
function foo(){
// 2
console.log(a, b)
// 3
var a = b =13
console.log(a, b)
}
foo()
console.log(a, b)
/* 输出:
undefined undefined
undefined "林一一"
13 13
12 13
*/
- 1处的 a, b 其实就是 window下面的属性为 undefined。
- 在函数内部由于变量提升机制
a
带var
一开始就是 undefined,b
不带var
将向上级作用域查找,找到全局作用域下的林一一
所以2处打印出来的就是undefined "林一一"
。 - 随后
a =13,window.b =13
,即原来b='林一一'
变成了b=13
,打印出13, 13
, - 最后第4处打印处
12, 13
。
自执行函数IIFE::特殊原因--IIFE 函数具备自己的作用域
内部:变量提升
var a = 'a';
(function(){
console.log(a);
var a;
})(a);
//undefined
var a = 10;
console.log(window.a);
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
//10 undefined 10 20
外部:不会函数提升
var a = 10;
(function c(){
})()
console.log(c)
// Uncaught ReferenceError: c is not defined
修改函数名的值无效
var a = 10;
(function a(){
console.log(a)
a = 20
console.log(a)
})()
// ƒ a(){a = 20 console.log(a)} ƒ a(){a = 20 console.log(a)}
参考链接:彻底解决 JS 变量提升| 一题一图,超详细包教包会😉 - 掘金
JS 扫盲:浅淡JavaScript运行机制和面试题 - 掘金