【JavaScript】ECMAS6(ES6)新特性概览(一):变量声明let与const、箭头函数、模板字面量全面解析

在这里插入图片描述

🔥 个人主页:空白诗
🔥 热门专栏:【JavaScript】

在这里插入图片描述

文章目录

    • 🌿 引言
    • 一、 `let` 和 `const` - 变量声明的新方式 🌟
      • 📌 `var`的问题回顾
      • 📌 `let`的革新
      • 📌 `const`的不变之美
    • 二、 Arrow Functions - 箭头函数,简洁之美 ✨
      • 📌 语法精简
      • 📌 普通函数与`this`的动态绑定
      • 📌 箭头函数与静态`this`绑定
        • 适用场景
        • 注意事项
      • 📌 小结
    • 三、 Template Literals - 字符串模板,插值新体验 💬
      • 📌 基础插值
      • 📌 多行字符串与保留格式
      • 📌 表达式与函数
      • 📌 标签化模板字面量
      • 📌 小结
    • 四、 Default Parameters - 参数默认值,告别undefined ❓
      • 📌 基本用法
      • 📌 复合默认值与逻辑判断
      • 📌 注意事项与实践建议
      • 📌 小结
    • 总结

在这里插入图片描述

🌿 引言

ES6,作为ECMAScript 2015的简称,标志着JavaScript编程语言的一个重要进化节点。它不是渐进的变化,而是一次飞跃式的更新,为开发者带来了一系列强大的新特性与语法糖,极大提升了代码的简洁性、可读性和运行效率。从新的变量声明方式letconst,到优雅的箭头函数模板字符串,再到让对象操作更为灵活的解构赋值增强的对象字面量ES6的每项改进都旨在让JavaScript适应日益复杂的应用场景,同时保持其作为脚本语言的活力与魅力。本文是深入探索这些核心特性的起点,为你铺开一条通向高效、现代JavaScript编程实践的道路。


一、 letconst - 变量声明的新方式 🌟

ES6之前的JavaScript世界,var作为声明变量的主力军,虽功不可没,却也因其变量提升(variable hoisting)和函数作用域(function scope)的特性,给开发者带来了不少困惑和潜在错误。随着ES6的登场,letconst的引入如同一股清流,为变量管理领域带来了革新与严谨性。

📌 var的问题回顾

  • 变量提升(Variabe Hoisting): 当你在函数内部使用var声明一个变量时,这个声明会被JavaScript引擎默默地“提升”到当前作用域的最顶部。尽管这不会提升变量的赋值操作,但会导致在声明前访问变量时不会抛出ReferenceError错误,而是输出undefined。这种机制有时会导致难以预料的结果,尤其是在涉及条件或循环时。

    function illustrateVarHoist() {
        console.log(bar); // 输出:undefined,证明变量被提升了
        var bar = "I'm hoisted!";
        console.log(bar); // 输出:I'm hoisted!
    }
    illustrateVarHoist();
    
  • 作用域限制(Scope Limitations): var声明的变量遵循函数作用域(function scope)或全局作用域(global scope),而不是块级作用域(block scope)。这意味着,在一个函数内部声明的var变量对整个函数都是可见的,而在任意代码块(如if语句或for循环)中声明的var变量实际上属于包含它的函数作用域或全局作用域。这可能导致在循环或条件判断中预期之外的变量共享问题。

    for (var i = 0; i < 3; i++) {
        setTimeout(function() {
            console.log(i); // 输出:3,3,3,因为i是在同一个作用域内被修改的
        }, 1000);
    }
    

以上代码展示了由于var的作用域特性,在循环结束后每个setTimeout回调访问的i都是循环结束时的值(3),而非每次迭代时的值。这强调了使用var时可能遇到的意料之外的副作用。

📌 let的革新

  • 块级作用域(Block Scoping): 引入let关键字是ES6对变量作用域处理的一次重大改进。与var的函数作用域不同,let声明的变量严格遵循块级作用域原则。这意味着,如果你在一个特定的代码块(例如if语句、for循环或者一对大括号内)使用let声明变量,那么这个变量仅在此块内有效,出了这个块就无法访问,从而有效避免了变量泄漏到外部作用域,减少了意外的变量覆盖问题。

    {
        let y = 5;
        console.log(y); // 输出 5
    }
    // console.log(y); // 这里会报错:y is not defined,体现了let的严格块级限制
    
    for (let i = 0; i < 3; i++) {
        setTimeout(function() {
            console.log(i); // 分别输出 0, 1, 2,每一次迭代i都是新的绑定
        }, 1000);
    }
    

在上面的循环例子中,每次循环迭代都会创建一个新的i变量实例,每个setTimeout回调都能记住自己迭代时i的值,解决了使用var时的闭包陷阱问题,这是let在处理循环中的一个显著优势,极大增强了代码的逻辑清晰度和可预测性。

📌 const的不变之美

  • 常量声明(Constant Declaration): const关键字的引入,为JavaScript开发者提供了一种定义不可变变量的方式。一旦使用const声明了一个变量并赋予初始值,该变量的值便被视为固定,任何尝试修改的操作都将引发错误。这促进了代码的清晰度和稳定性,鼓励开发者明确哪些数据是程序状态中的常量,减少意外变更的风险。

    const MAX_SCORE = 100; // 游戏中的最高分,不应改变
    // MAX_SCORE = 200; // 这里会导致错误:Assignment to constant variable.
    
    // 对象和数组的特殊情况:
    const settings = { difficulty: 'hard' };
    // settings = {}; // 错误:不能重新赋值
    settings.difficulty = 'easy'; // 但是可以修改对象的属性,因为const冻结的是引用,非对象内容本身
    console.log(settings); // 输出:{ difficulty: 'easy' }
    

通过const,开发者能够明确标识出那些设计为不应更改的值,无论是基础数据类型还是对象的引用,这对于维护大型代码库尤其重要,因为它提高了代码的可读性和可维护性。结合let的块级作用域特性,两者共同为JavaScript的变量管理带来了一场革命,推动了更加严谨和高效的编程实践。

这里只做一些简单介绍,更多关于 varletconst以及变量提升作用域逻辑TDZ 的内容在之前的一篇博客:
JavaScript基础知识强化:变量提升、作用域逻辑及TDZ的全面解析


二、 Arrow Functions - 箭头函数,简洁之美 ✨

箭头函数(=>)作为ES6的一项革新特性,显著简化了函数的语法,同时以一种新颖的方式解决了长期困扰开发者的关于this关键字上下文绑定的问题,为JavaScript函数表达式赋予了新的生命和优雅。

📌 语法精简

与传统函数声明或函数表达式不同,箭头函数采用了一种更加紧凑的语法结构,摒弃了function关键字,并且在函数体仅包含一个表达式时,允许省略花括号 {}return 语句,直接返回该表达式的结果。

// 传统函数声明
function add(a, b) {
    return a + b;
}

// 箭头函数表达式
const add = (a, b) => a + b; // 直接返回求和结果

// 传统函数表达式
[1, 2, 3].map(function(x) {
    return x * x;
});

// 使用箭头函数,提升代码简洁度
[1, 2, 3].map(x => x * x);

📌 普通函数与this的动态绑定

在经典的函数实现中,this的值由函数调用的环境在运行时动态确定,这可能导致在复杂调用链或异步编程中出现预期之外的this行为。

function identify() {
    console.log(this.name);
}

const obj = { name: "Object Context", identify: identify };

// 正常情况下的`this`绑定
obj.identify(); // 输出 "Object Context"

// 独立调用时,非严格模式下的`this`通常指向全局对象
identify(); // 可能在浏览器中输出 "Window" 或在Node.js中输出 "global"

在面试时经常会遇到的一个问题是:如何改变普通函数中this的指向❓
一种是使用.call(), .apply(), 或 .bind()方法,这三种方法在本文中不做详细解释,详细区别可查看另一篇博客:JavaScript中call、apply与bind的区别
一种是手动设置that = this_this去保存当前的this值,然后在需要的地方使用这个变量
还有一种就是使用箭头函数,将在下文详细解释

📌 箭头函数与静态this绑定

箭头函数的核心变革在于其处理this的方式。它们不会创建自己的this,而是直接沿用外层(词法作用域)的this值,这意味着箭头函数内的this在定义时即被固定,调用上下文的改变不会影响到它。

const objArrow = { name: "Arrow Context" };

// 箭头函数捕获定义时的`this`
const identifyArrow = () => console.log(this.name);

// 即便函数被赋值或传递,其`this`依然绑定到定义时的环境
objArrow.identifyArrow = identifyArrow;
objArrow.identifyArrow(); // 明确输出 "Arrow Context"

// 直接调用,箭头函数的`this`遵循外层作用域
identifyArrow(); // 输出取决于外部上下文,可能是全局对象的名称
适用场景
  • 事件处理与回调:在事件监听或异步操作如setTimeoutPromise回调中,使用箭头函数可以避免this丢失问题。

  • 对象方法:虽然通常不推荐将箭头函数直接作为对象的方法(因为它无法直接绑定对象实例作为this),但在一些场景下,如需要保持外层作用域的this时,箭头函数依然有用。

  • 函数内部函数:在另一个函数内部定义的箭头函数,通常用于保留外层的this,避免闭包问题。

注意事项
  • 不可用作构造函数:箭头函数不能用new调用,因为它没有自己的this,没有原型属性。
  • argumentssuper:箭头函数不绑定自己的arguments,且不能使用super关键字,需要时考虑使用其他方案。

📌 小结

  • 普通函数this是动态的,调用时根据上下文确定,适用于需要灵活上下文的场景。
  • 箭头函数通过静态绑定this,确保了函数内部的上下文一致性,特别适合用于闭包、事件处理和异步编程等对this稳定有高要求的场景。

通过对比分析,我们深入理解了箭头函数在处理this问题上的独特优势,以及它如何通过简化语法和增强逻辑清晰度来提升JavaScript代码的质量和可维护性。在实际编码实践中,合理选择普通函数与箭头函数,能够有效提升程序的可靠性和开发效率。


三、 Template Literals - 字符串模板,插值新体验 💬

自从ES6引入模板字面量(Template Literals)以来,处理字符串和嵌入变量或表达式变得更加直观和简洁。这种以反引号(`)包围的字符串格式,不仅改善了代码的可读性,还提供了强大的插值功能,让我们能够以一种接近自然语言的方式构造复杂的字符串。

📌 基础插值

基本的插值操作通过${expression}来完成,其中expression可以是任何有效的JavaScript表达式,包括变量、运算符乃至函数调用。

const name = "Alice";
const age = 28;

// 使用模板字面量进行字符串拼接
console.log(`My name is ${name}, and I am ${age} years young.`);

// 输出:My name is Alice, and I am 28 years young.

📌 多行字符串与保留格式

除了变量插值,模板字面量还天然支持多行字符串,无需使用转义字符,这对于编写HTML片段、SQL查询或是任何需要跨多行的文本内容尤其方便。

const poem = `The woods are lovely, dark and deep,
But I have promises to keep,
And miles to go before I sleep,
And miles to go before I sleep.`;

console.log(poem);

📌 表达式与函数

模板字面量中的插值不仅仅局限于简单变量,你甚至可以直接执行函数或计算表达式,并将其结果嵌入到字符串中。

function getGreeting(hour) {
    return hour < 12 ? "Good morning" : "Good afternoon";
}

const currentHour = new Date().getHours();
console.log(`${getGreeting(currentHour)}, ${name}! How's your day going?`);

📌 标签化模板字面量

进一步地,通过“标签模板”功能,你可以自定义模板字面量的处理逻辑。这为字符串的预处理(如过滤、格式化等)提供了无限可能。

function highlight(text) {
    return text.map((part, index) => {
        if (index % 2 === 0) return part;
        else return `<strong>${part}</strong>`;
    }).join('');
}

const sentence = `Cup of coffee, slice of cake`;
console.log(highlight`I'd like a ${sentence}`);

📌 小结

模板字面量以其便捷的插值语法、多行文本的支持以及通过标签化进行的高级处理能力,彻底改变了JavaScript中字符串处理的方式。它们让代码更易于阅读和维护,同时也大大提高了开发者在构建动态内容时的灵活性和效率。掌握这一特性,对于现代JavaScript编程至关重要。


四、 Default Parameters - 参数默认值,告别undefined ❓

ES6的参数默认值功能是JavaScript函数定义的一次重要进化,它赋予了开发者为函数参数指定默认值的能力,从而在调用函数时即使未提供相应实参,也能避免undefined的困扰。此特性显著提升了代码的健壮性与灵活性,使函数调用更加优雅流畅。

📌 基本用法

在函数声明时,通过在参数名后紧接赋值运算符=及默认值即可设置参数的默认值。如下例所示,当调用greet()时未提供参数,name自动采用默认值Stranger

function greet(name = "Stranger") {
    console.log(`Hello, ${name}!`);
}

greet(); // 输出:Hello, Stranger!
greet("Alice"); // 输出:Hello, Alice!

📌 复合默认值与逻辑判断

默认值的设定远不止限于简单字面量,它能够是任何有效的JavaScript表达式,甚至是函数调用,这为参数处理引入了丰富的逻辑潜力。

function calculateArea(width, height = width * 2) {
    return width * height;
}

console.log(calculateArea(10)); // 未指定高度,使用默认值(宽度的两倍),输出:200
console.log(calculateArea(10, 5)); // 指定了高度,覆盖默认逻辑,输出:50

📌 注意事项与实践建议

  • 顺序与依赖: 如果函数有多个参数且其中某些依赖前面的参数值来计算默认值,务必确保前面的参数都有明确的值,否则默认值逻辑可能不会按预期执行。

  • 默认值共享: 注意默认值如果是引用类型(如数组、对象),所有函数调用将共享同一默认实例,修改一个实例会影响到其他调用。为避免这种情况,可以考虑使用函数来生成默认值。

  • 默认值惰性评估: 默认值在函数定义时计算,对于包含复杂计算或副作用的默认值需谨慎使用。

📌 小结

默认参数机制的加入,标志着JavaScript函数设计步入了一个更加人性化和健壮的新阶段。它不仅简化了函数接口的使用,减少了因遗漏参数导致的错误,还促进了代码的清晰度与可维护性,无疑是现代JavaScript开发中不可或缺的一环。掌握并善用此特性,将使你的代码更加稳健且优雅。


总结

本文深入探讨了ECMAS6中对JavaScript变量声明方式的重要革新,重点聚焦于letconst的引入,以及箭头函数与模板字面量的使用,这些特性如何重塑了现代JavaScript编程实践。

  • letconst声明:打破了var的限制,let带来了块级作用域,确保变量在定义块内有效,避免了变量污染;const确保不可变性,加强了代码的安全性与可读性。

  • 箭头函数:简化了函数语法,提升了可读性,解决了this绑定难题,尤其在异步编程与事件处理中的应用显著。

  • 模板面量:提供了一种动态构造字符串的新方式,支持多行文本与表达式插值,增强了代码的自然度与灵活性。

这些特性综合起来,ECMAS6不仅增强了JavaScript的严谨性与代码质量,还极大地提高了开发效率,使开发者能编写出更健壮、易维护、可读性强的应用程序。理解这些核心机制,是成为JavaScript高手的关键路径。

后续我们将继续深入了解ES6新特性,例如class类、模块、异步处理promise、生成器函数generatorsmapset数据结构…等等。当然其中有些内容在之前的博客也有详细探讨过,内容都在👉🏻 🔥 专栏:【JavaScript】。感谢大家支持~ ❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/663328.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CasaOS玩客云安装全平台高速下载器Gopeed并实现远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Spring-Cloud-CircuitBreaker-Resilience4j (3.1.1)

介绍 Resilience4j 是一个专为函数式编程而设计的轻量级容错库。Resilience4j 提供高阶函数&#xff08;装饰器&#xff09;&#xff0c;以增强任何功能接口、lambda 表达式或方法引用&#xff0c;包括断路器、速率限制器、重试或隔板。您可以在任何函数接口、lambda 表达式或…

每日复盘-20240530

今日重点关注&#xff1a; 20240530 六日涨幅最大: ------1--------300637--------- 扬帆新材 五日涨幅最大: ------1--------300637--------- 扬帆新材 四日涨幅最大: ------1--------300637--------- 扬帆新材 三日涨幅最大: ------1--------301129--------- 瑞纳智能 二日涨…

Stable Diffusion AI绘画:从创意词汇到艺术图画的魔法之旅

文章目录 一、Stable Diffusion的工作原理二、从提示词到模型出图的过程三、Stable Diffusion在艺术创作中的应用《Stable Diffusion AI绘画从提示词到模型出图》内容简介作者简介楚天 目录前言/序言本书特色特别提示 获取方式 在科技的飞速发展中&#xff0c;Stable Diffusion…

读取YUV数据到AVFrame并用多线程控制帧率

文件树&#xff1a; 1.xvideo_view.h class XVideoView { public:// 像素格式枚举enum Format { RGBA 0, ARGB, YUV420P };// 渲染类型枚举enum RenderType { SDL 0 };// 创建渲染对象的静态方法static XVideoView* Create(RenderType type SDL);// 绘制帧的方法bool DrawF…

Word下一页怎么操作?6个操作方法分享!

在使用Word进行文档编辑时&#xff0c;经常需要设置分页、跳转页面或者对页面进行特定的布局调整。其中&#xff0c;“下一页”这一操作通常涉及到页面布局、分页符的插入、页面跳转等多个方面。 Word下一页怎么操作&#xff1f;很简单&#xff0c;方法已经准备好啦&#xff0…

Python代码:二十五、有序的列表

1、题目 创建一个依次包含字符串P、y、t、h、o和n的列表my_list&#xff0c;先使用sorted函数对列表my_list进行临时排序&#xff0c;第一行输出排序后的完整列表&#xff0c;第二行输出原始的列表。再使用sort函数对列表my_list进行降序排序&#xff0c;第三行输出排序后完整…

20240531瑞芯微官方Toybrick TB-RK3588开发板在Debian11下的关机尝试

20240531瑞芯微官方Toybrick TB-RK3588开发板在Debian11下的关机尝试 2024/5/31 9:10 https://t.rock-chips.com/forum.php?modforumdisplay&fid51 在Toybrick的论坛以关键词搜索&#xff1a;关机 可以找到抱怨这个的人很多&#xff01; &#xff08;一&#xff09;【失败…

深入分析 Android Service (三)

文章目录 深入分析 Android Service (三)1. Service 与 Activity 之间的通信2. 详细示例&#xff1a;通过绑定服务进行通信2.1 创建一个绑定服务2.2 绑定和通信 3. 优化建议4. 使用场景5. 总结 深入分析 Android Service (三) 1. Service 与 Activity 之间的通信 在 Android …

linux nohup命令详解:持久运行命令,无视终端退出

nohup &#xff08;全称为 “no hang up”&#xff09;&#xff0c;用于运行一个命令&#xff0c;使其在你退出 shell 或终端会话后继续运行。 基本语法 nohup command [arg1 ...] [&> output_file] &command 是你想要运行的命令。[arg1 ...] 是该命令的参数。&am…

Spring Boot 整合 spring-boot-starter-mail 实现邮件发送和账户激活

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

Wireshark抓包后的报文太大,如何拆分?

背景&#xff1a;抓包获取到一个400多兆的网络数据包.pcapng文件&#xff0c;使用wireshark软件可以正常打开。但需要把文件导出为.json文件&#xff0c;从而方便对报文内容做过滤分析。使用wireshark自带的导出功能导出后发现生成的.json文件大小为2G多&#xff0c;使用notepa…

Java-----Comparable接口和Comparator接口

在Java中&#xff0c;我们会经常使用到自定义类&#xff0c;那我们如何进行自定义类的比较呢? 1.Comparable接口 普通数据的比较 int a10;int b91;System.out.println(a<b); 那自定义类型可不可以这样比较呢&#xff1f;看一下代码 我们发现会报错&#xff0c;因为自定义…

电机控制系列模块解析(25)—— 过压抑制与欠压抑制

一、概念解析 变频器作为一种重要的电机驱动装置&#xff0c;其内置的保护功能对于确保系统安全、稳定运行至关重要。以下是关于变频器过压抑制、欠压抑制&#xff08;晃电抑制&#xff09;、发电功率限制、电动功率限制等保护功能的详细说明&#xff1a; 过压抑制 过压抑制是…

YoloV8改进策略:卷积篇|基于PConv的二次创新|附结构图|性能和精度得到大幅度提高(独家原创)

摘要 在PConv的基础上做了二次创新,创新后的模型不仅在精度和速度上有了质的提升,还可以支持Stride为2的降采样。 改进方法简单高效,需要发论文的同学不要错过! 论文指导 PConv在论文中的描述 论文: 下面我们展示了可以通过利用特征图的冗余来进一步优化成本。如图3所…

golang web补充知识:单元测试

文章目录 golang 单元测试引言单元测试的重要性Go语言单元测试的优势 Go语言单元测试基础testing包辅助测试函数运行单元测试 Mock技术Mock简介GoMock框架介绍编写Mock代码使用Mock进行单元测试 面向测试编程&#xff08;TDD&#xff09;TDD简介TDD的优势TDD的基本步骤Go语言中…

discuz如何添加主导航

大家好&#xff0c;今天教大家怎么样给discuz添加主导航。方法其实很简单&#xff0c;大家跟着我操作既可。一个网站的导航栏是非常重要的&#xff0c;一般用户进入网站的第一印象就是看网站的导航栏。如果大家想看效果的话可以搜索下网创有方&#xff0c;或者直接点击查看效果…

大数据中的电商数仓项目:探秘业务的核心

我学习完一个电商数仓的项目和电影实时推荐项目&#xff0c;便兴冲冲的去面试大数据开发岗&#xff0c;在面试的时候&#xff0c;面试官总是喜欢问&#xff0c;聊聊你为什么要做这个项目以及你这个项目有哪些业务&#xff1f; 我心想&#xff0c;为什么要做这个业务&#xff1f…

重学java 52.集合 斗地主案例

你太锐利了&#xff0c;这些年来&#xff0c;风霜雨雪&#xff0c;踉跄清冷&#xff0c;我相信你所有的苦楚 —— 24.5.30 1 案例介绍 按照斗地主的规则&#xff0c;完成洗牌发牌的动作。 具体规则: 使用54张牌打乱顺序,三个玩家参与游戏&#xff0c;三人交替摸牌&#xff0c…

ipv6基础

地址 前缀子网主机位 PI法则3.14 前缀&#xff1a;3个16位 子网&#xff1a;1个16位 接口ID&#xff1a;4个16位 地址分类 未指定地址 ::/128 &#xff0c;类似于0.0.0.0 本地回环地址 ::1/128 &#xff0c;用于本地测试&#xff0c;类似于127.0.0.1 本地链路地址&#x…