JS预定义解析/编译(变量提升):var、let、const(声明无赋值)、function(声明+赋值)

51 篇文章 14 订阅
7 篇文章 0 订阅

目录

声明前访问

不报错

function:声明+赋值

除了自执行函数IIFE(隔绝外部作用域),箭头函数(无function)

var:声明不赋值

报错

let 、const、calss :声明不赋值,暂时性死区访问

不带var:无提升,is not defined

var a=b=1  等价于var a=1;b=1

变量重复声明

可重复声明

无var

var、function:只提升一次

不允许重复声明:let、const,SyntaxError

function和var重名/共用一个标识名

访问变量时机

var声明前:undefined

var声明后:js用到变量时才赋值,可能覆盖

let、const 、class:块级作用域

暂时性死区:作用域/使用起点~变量声明

顶级作用域

function和有无var

浏览器环境:在全局对象window上创建属性

包括块作用域{ }

不会在全局对象上创建属性:

node.js环境:全局对象global

strict严格模式:不允许无var声明,不允许挂载window,this为undefined

let 不会在全局对象this上创建属性

函数作用域:(有无var、let、const)局部变量,外部不可访问

内部作用域优先级高于外部作用域

自执行函数IIFE::特殊原因--IIFE 函数具备自己的作用域

内部:变量提升

外部:不会函数提升

 修改函数名的值无效

*编译

分词/词法分析:分解(var a=2=> var,a,=,2)

解析/语法分析:词法数组=>程序语法 结构的“抽象语法树”(a->2)(Abstract Syntax Tree,AST)

代码生成:将 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

letconst 、class:块级作用域

在类的方法中,this 关键字指向当前实例,而不是指向全局对象。

暂时性死区:作用域/使用起点~变量声明

“暂时性”区:这个区域取决于代码执行的时间点,而不是代码编写的顺序。

{
  // 暂时性死区始于作用域开头
  const func = () => console.log(letVar); // 

  // 在暂时性死区内访问 letVar 会抛出 `ReferenceError`

  let letVar; // 暂时性死区结束(对 letVar 而言)
  func(); // 在暂时性死区外调用,会输出 undefined
}

用 letconst 或 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. 1处的 a, b 其实就是 window下面的属性为 undefined。
  2. 在函数内部由于变量提升机制 avar 一开始就是 undefined,b不带var 将向上级作用域查找,找到全局作用域下的林一一所以2处打印出来的就是 undefined "林一一"
  3. 随后 a =13,window.b =13,即原来 b='林一一' 变成了 b=13,打印出13, 13
  4. 最后第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运行机制和面试题 - 掘金

*编译

分词/词法分析:分解(var a=2=> var,a,=,2)

解析/语法分析:词法数组=>程序语法 结构的“抽象语法树”(a->2)(Abstract Syntax Tree,AST)

代码生成:将 AST 转换为可执行代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值