为什么要引入let const?

先看几道例题,以下代码会输出什么?

ini 复制代码
console.log(text);
var text = '学习前端';

输出:undefined

arduino 复制代码
console.log(text);
let text = '学习前端'

输出:ReferenceError:Cannot access 'text' before initialization。

arduino 复制代码
console.log(text);
if(true){
  var text = '学习前端'
}

输出:undefined

arduino 复制代码
console.log(text);
if(false){
  var text = '学习前端'
}

输出:undefined

arduino 复制代码
console.log(text);
if(true){
  let text = '学习前端'
}

输出:ReferenceError: text is not defined

arduino 复制代码
console.log(text);

function init(){
  var text = '学习前端'
}

输出:ReferenceError: text is not defined

相信彦祖们都轻松拿捏,为什么var会有这些不寻常的表现呢?为什么要引入let const呢?

变量提升

使用var声明的变量会存在变量提升。什么是变量提升呢?是js代码编译的过程中,js引擎把声明部分提升到代码开头这个行为。并且会给变量设置为一个默认值undefined、

ini 复制代码
console.log(text);
var text = '学习前端';

模拟这段代码被编译后的结果:

ini 复制代码
vat text = undefined;
console.log(text);
text = '学习前端';

变量提升到代码开头,这个开头是哪里的开头呢? 是全局的开头? 还是函数的开头?还是一个语句块的开头?

这就需要先去了解作用域

作用域

简单的理解:作用域就是变量与函数的可访问范围。

再ES6之前,作用域只有两种:全局作用域函数作用域。

这两个作用域也就控制了变量提升的位置。

arduino 复制代码
console.log(text); // 报错 text is not defined

function init(){
  var text = '学习前端'
}

在ES6之前,由于没有块级作用域的原因,总会有一些奇怪的现象。

arduino 复制代码
console.log(text); //undefined
if(false){
  var text = '学习前端'
}

可以看到这段代码也是被提升了。 和if条件没有关系, 可能有些初学者会认为条件没满足,是不会创建text,这个观点是错误的。

还有在循环块中, 循环结束之后还是可以访问到变量。

css 复制代码
for(var i = 0; i < 4;i++){
  
}

console.log(i); //4

为了解决上述的问题, ES6引入了let const 关键字。这样js也拥有了块级作用域

scss 复制代码
//全局作用域
var text = '学习前端';

//if块
if(true){};

//for循环块
for(let i = 0; i<100; i++){
  
}

//块
{}

let和const

使用let和const声明的变量只能在块级作用域中访问。

特点:

  1. 不会被变量提升
arduino 复制代码
console.log(text);  //ReferenceError: text is not defined
if(true){
  let text = '学习前端'
}
  1. 不能重复声明
  2. 临时性死区:在声明前访问变量会报错。
arduino 复制代码
if (true) {
  console.log(text); //ReferenceError: Cannot access 'text' before initialization
  let text = "学习前端";
}

不同点:let声明之后可以修改, const声明的值,不能被修改。

截止到现在,开篇的几个例题都是可以解释了, 但还可以再深入了解一下。

JS如何支持块级作用域的呢?

JS是如何保持了var的变量提升, 又保持了块级作用域呢?

在执行一段代码之前,第一步会进行编译创建执行上下文,使用var声明的变量会放在变量环境中,使用let const声明的变量,会放在词法环境中。

在访问一个变量的时候,会先访问词法环境 ,再访问变量环境

词法环境内部维护了一个栈结构,解析到一个作用域块,就会把这个块压入栈中,当这个作用域执行完毕之后,就会将这块弹出, 具体查找方式沿着词法环境的栈顶向下查询,找不到再去变量环境中查找。

javascript 复制代码
// 全局词法环境
let globalVar = '全局变量';


function func() {
    // func 的词法环境
    let localVar = '局部变量';
    let a = 1;
    // func 的 变量环境
    var c = 2;
    {
      //当前块的词法环境
      let a = 3;
      console.log(a); //3 ,从当前词法环境中找
      console.log(c); //2  从当前词法环境中没找到,去变量环境中找到了
    }
    console.log(a);//1 从词法作用域中找
    console.log(localVar); // 从当前 func 的词法环境访问
    console.log(globalVar); // 从全局词法环境访问
}

func(); // 3 ,2 ,1 ,局部变量,全局变量

上述代码中,func函数中 解析到块结构后,将这个块压入到栈中,访问a变量时,从栈顶开始查找,这个块执行结束后,就会被弹出; 17行代码再去访问a变量时,从栈顶开始查找,现在的词法环境栈中只有func的块,所以输出了1。

整理下话术:

面试官:说一说var let const的区别

首先这三个都是JS中用于声明变量的。他们的区别是

  1. 在作用域方面,var是函数作用域,在函数作用域中使用var声明变量之后, 整个函数中都可以访问到,在函数外无法访问,而let和const是块级作用域,由大括号括起来的块中,只能被该块访问。
  2. 使用var声明的变量,存在变量提升,表现为在声明语句之前可以访问该变量,但是值为undefined。let和const不存在变量提升,在声明之前存在暂时性死区,访问会报错。
  3. 重复声明方面,var可以重复声明同一个变量,后者会覆盖前者。let和const 不允许重复声明相同变量。
  4. 值修改方面,var和let可以对声明后的值进行重新赋值,而const不允许。
  5. 在创建执行上下文时,var被放在了变量环境中,而let和const声明的变量放在了词法环境中,在访问一个变量时,先访问词法环境再访问变量环境。

leetcode

力扣题目链接(opens new window)

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

分析:题目中的关键字,有序,只有一个目标值,使用二分法。

ini 复制代码
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function(nums, target) {
    let left = 0;
    let right = nums.length - 1;
    while(left <=right){
        const mind = Math.floor((left + right) /2)
        if(target > nums[mind]){
            left = mind + 1
        }else if(target < nums[mind]){
            right = mind - 1
        }else{
            return mind
        }
    }
    return -1
};
相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax