为什么要引入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 分钟前
CSS3学习教程,从入门到精通, CSS3 盒子模型的详细语法知识点及案例代码(23)
前端·javascript·css·学习·css3·html5·java后端开发
Gerry-Xu15 分钟前
鸿蒙篇:vp、fp、px
前端·javascript·css
东东__net17 分钟前
26_ajax
前端·javascript·ajax
Riesenzahn19 分钟前
怎么把项目里的webpack换成vite?
前端·javascript
Riesenzahn21 分钟前
vite是如何进行热更新的?
前端·javascript
小浣熊喜欢揍臭臭23 分钟前
手动搭建并配置react项目(webpack5)
前端·react.js·前端框架
爱爬山的老虎28 分钟前
【CSS】相对位置小练习
前端·javascript·css
Jiaberrr36 分钟前
介绍几种创意登录页(含完整源码)
前端·javascript·css·elementui·css3
_Lok39 分钟前
Vue3 跨标签页通信攻略:四大主流方案解析
前端
打野赵怀真40 分钟前
举例说明CSS特性检测的方式有哪些?
前端·javascript