
文档教程前端【免费下载链接】Web千古前端图文教程超详细的前端入门到进阶知识库。从零开始学前端做一名精致优雅的前端工程师。项目地址https://gitcode.com/gh_mirrors/we/Web点击查看免费下载导读本篇文章以《11-Node.js/ES6.md》为骨架系统梳理 ES6ECMAScript 2015的诞生背景、核心语法与工程化落地方式并结合本仓库 05-JavaScript基础ES6语法 系列文档与 ES6 模块化实战 进行深度扩充。读者学完后将掌握 let/const 块级作用域、模板字符串、箭头函数、参数默认值、剩余参数与展开运算符并能用 export/import 完成 ES6 模块化开发以及借助 Babel Browserify 将其编译成浏览器可运行的 ES5 代码。一、ES6 是什么ECMAScript 语言标准ECMAScript 是 JS 的语言标准由 ECMA 国际标准化组织制定具体由第 39 号技术专家委员会TC39负责成员包括 Microsoft、Mozilla、Google 等公司。简单来说ECMAScript 是 JS 的语言标准而 ES6 是新的 JS 语法标准详见 01-ES5和ES6的介绍。发展历史1995 年ECMAScript 诞生1997 年ECMA 发布 ECMA-262 标准推出 ECMAScript 1.01999 年发布 ES32009 年发布 ECMAScript 5.0简称ES5新增 forEach、Object.keys、Object.create 等 API 与 JSON 标准2011 年发布 ECMAScript 5.1成为 ISO 国际标准2015 年 6 月ES6 正式发布即 ECMAScript 2015按版本号叫 ES6按年份叫 ES2015二者指的是同一个版本20162020 年每年 6 月发布一个新版本ES2016、ES2017、ES2018、ES2019、ES2020此后保持每年一版的节奏。需要特别说明的是ES6 在实际语境中往往是一个泛指泛指 ES2015 及后续的版本。很多人在做业务选型时倾向 jQuery而 jQuery 的语法偏向 ES3现在主流的 Vue.js 和 React.js 默认语法都用 ES6。ES6 的改进与目标ES6 之前的变量提升会导致程序运行时存在不可预测性ES6 通过let、const优化了这一点ES6 新增了常量、作用域、对象代理、异步处理、类、继承等功能这些在 ES5 中实现较复杂ES6 对它们进行了封装ES6 的目标是让 JS 语言可以编写复杂的大型应用程序成为企业级开发语言。二、ES6 的其他优势为什么值得学除了语法本身原文档还强调了 ES6 的两大现实优势使用 Babel 语法转换器支持低端浏览器写完 ES6 代码后可通过 Babel 将 ES6 转换为 ES5从而兼容不支持 ES6 的旧浏览器如 IE 11流行的库基本都是基于 ES6 构建React 默认使用 ES6 语法开发Vue 同样如此。关于 Babel 的完整环境配置流程npm init、安装 babel-cli、配置 .babelrc、npm run build本仓库有专门一篇实战文档ES5和ES6的介绍含 Babel 环境配置建议配合阅读。三、ES6 常用语法概览原文档给出的 ES6 语法总览包含以下板块块级作用域let / const字符串模板字符串、字符串扩展方法对象扩展、解构赋值函数扩展参数默认值、箭头函数、展开运算符类class模块化export / import下文按这条主线逐一展开并给出可运行的最小示例。四、作用域let 和 const4.1 基本用法用let定义变量替代var用const定义常量定义后不可修改两者都具备块级作用域作用域与{}有关。let a1 haha; const name smyhvae;4.2 var 的全局污染问题ES5 回顾{ var a 1; } console.log(a); // 输出 1var 是全局声明的区块不影响它的作用域var a 1; { var a 2; } console.log(a); // 输出 2var 没有块级作用域后面声明覆盖前面结论ES5 语法中用var定义的变量容易造成全局污染。不考虑浏览器兼容性时应尽量使用 ES6 的let/const。4.3 let定义变量只在局部起作用{ let a hello; } console.log(a); // 报错Uncaught ReferenceError: a is not definedvar a 2; { let a 3; } console.log(a); // 输出 2块内的 let 不影响外层4.4 经典面试题for 循环中的 var 与 let用 var 声明for (var i 0; i 10; i) { console.log(循环体中: i); } console.log(循环体外: i); // 输出 10i 是全局作用域的变量用 let 声明for (let i 0; i 10; i) { console.log(循环体中: i); // 每次循环在 {} 块级作用域中重新定义新的变量 i } console.log(循环体外: i); // 报错i 只在块级作用域内生效关键点每次循环都会产生一个块级作用域每个块级作用域中会重新定义一个新的变量 i。这也是解决按钮点击事件闭包陷阱的标准方案——用let声明循环变量后每个按钮绑定各自的 i而不是共享同一个最终值。详细对比可参考仓库中的 04-ES6变量 let、const 和块级作用域 与 01-var、let、const的区别。4.5 const定义常量const name smyhvae; // 定义常量用const声明的常量只在局部块级作用域内起作用声明时必须赋值否则报错。常量就是值内存地址不能变化的量适合声明业务层不再变化的数据。4.6 let / const 的特点汇总重要不属于顶层对象 Windowlet/const声明的变量不会挂到 window 上不允许重复声明同一作用域内重复let a会报错不存在变量提升暂时性死区TDZ使用 let/const 声明的变量必须先声明再使用声明语句必须放在使用之前否则报错const name qianguyihao; function foo() { console.log(name); // 报错Cannot access name before initialization const name hello; } foo();TDZ 是一种保护机制能帮助我们养成良好的编程习惯。支持块级作用域。与之相反var声明存在变量提升、可以重复声明、没有块级作用域。共同点全局作用域中定义的变量可以在函数中使用函数中声明的变量只能在函数及其子函数中使用外部无法访问。4.7 补充ES5 中如何定义常量ES5 中可通过Object.defineProperty定义常量Object.defineProperty(window, PI, { value: 3.14, writable: false, }); console.log(PI); // 3.14 PI 6; // 尝试修改 console.log(PI); // 3.14修改失败五、模板字符串传统写法下的字符串拼接比较繁琐而且容易出错var name smyhvae; var age 26; console.log(name: name ,age: age); // 传统写法ES6 语法可以直接用**反引号在 tab 键上方**包裹模板并通过${}嵌入变量var name smyhvae; var age 26; console.log(name:${name},age:${age}); // ES6 写法注意单引号是普通字符串反引号才是模板字符串。六、函数扩展ES6 在函数扩展方面新增了多项特性箭头函数、参数默认值、参数解构赋值、剩余参数、扩展运算符、this 绑定、尾调用等。本节覆盖原文档列出的三个核心点。6.1 参数默认值传统写法需要手动兜底比较啰嗦function fn(param) { let p param || hello; console.log(p); }ES6 写法直接在参数上指定默认值缺省值function fn(param hello) { console.log(param); }规则方法被调用时如果没有给参数赋值就用默认值如果赋了新的值就用新值。例如箭头函数配合默认值var fn2 (a, b 5) { console.log(haha); return a b; }; console.log(fn2(1)); // 第二个参数使用默认值 5输出 6 console.log(fn2(1, 8)); // 输出 9两个提醒默认值的后面不能再有没有默认值的变量如(a, b, c)中给 b 设默认值就必须给 c 也设默认值默认值表达式中的x指的是参数作用域中的同名参数而不是外层变量。例如let x smyh; function fn(x, y x) { console.log(x, y); } fn(vae); // 输出vae vaey 取的是参数 x 的值6.2 箭头函数定义语法(参数1, 参数2 ...) { 函数体 }如果有且仅有 1 个形参()可以省略如果函数体内有且仅有 1 条语句且该语句是 return 语句{}可以省略箭头函数没有函数名通常将其赋值给一个变量通过变量名调用。传统写法与 ES6 写法的对比// 传统写法 function fn1(name) { console.log(name); } fn1(smyhvae); // ES6 写法 var fn2 (name) { console.log(name); }; fn2(smyhvae);两段代码执行结果一样。给参数加默认值var fn2 (name enen) { console.log(name); }; fn2(); // 参数用默认值 enen fn2(smyhvae); // 用传入值典型应用1 秒后执行一段代码setTimeout(() { console.log(something); }, 1000);函数体只有一条 return 语句时大括号可以省略const myDouble x x * 2; console.log(myDouble(5)); // 打印结果为 10箭头函数的好处简写代码语法更简洁保持 this 的作用域普通函数中 this 指向调用它的对象而箭头函数本身不绑定 thisthis 指向箭头函数定义位置的 this。const obj { name: 千古壹号 }; function fn1() { console.log(this); // 第一个 this return () { console.log(this); // 第二个 this }; } const fn2 fn1.call(obj); fn2(); // 打印结果obj、obj代码解释箭头函数在fn1()中定义第二个 this 与第一个 this 指向同一位置执行fn1.call(obj)后第一个 this 指向 obj所以第二个 this 也指向 obj。面试题箭头函数的 this 指向var name 许嵩; var obj { name: 千古壹号, sayHello: () { console.log(this.name); }, }; obj.sayHello(); // 打印结果许嵩原因obj对象不产生作用域sayHello箭头函数实际仍定义在 window 中所以这里的 this 指向 window。更完整的讲解见 06-ES6箭头函数。6.3 剩余参数与展开运算符剩余参数...args将不确定数量的剩余元素放到一个数组中。当实参个数大于形参个数时不必像 ES5 那样报错const fn (...args) { console.log(args[0]); console.log(args[1]); console.log(args[2]); console.log(args[3]); }; fn(1, 2); fn(1, 2, 3); // 不会报错未匹配到的参数为 undefined注意args之后不能再加别的参数。剩余参数也可与其他形参搭配function fn1(first, ...args) { console.log(first); // 10 console.log(args); // 数组[20, 30] } fn1(10, 20, 30);典型应用——参数求和const sum (...args) { let total 0; args.forEach(item total item); return total; }; console.log(sum(10, 20, 30)); // 60剩余参数与解构赋值配合const students [张三, 李四, 王五]; let [s1, ...s2] students; console.log(s1); // 张三 console.log(s2); // [李四, 王五]展开运算符与剩余参数相反把数组或对象拆分成逗号分隔的参数序列const arr [10, 20, 30]; console.log(...arr); // 10 20 30逗号被当作 console.log 的参数分隔符常见应用场景数组拷贝开辟新内存地址let arr1 [www, smyhvae, com]; let arr2 [...arr1]; // arr2 重新开辟内存地址 arr2.push(你懂得); console.log(arr1); // www,smyhvae,com不受影响合并数组let arr1 [王一, 王二, 王三]; let arr2 [王四, 王五, 王六]; let arr3 [...arr1, ...arr2]; // 方法1合并为新数组 arr1.push(...arr2); // 方法2就地追加将伪数组或可遍历对象转换为真正的数组const myDivs document.getElementsByClassName(div); const divArr [...myDivs]; // 利用扩展运算符将伪数组转为真数组补充也可使用Array.from(arrayLike)实现同样的转换。以上内容的完整版见 07-剩余参数和扩展运算符。七、解构赋值解构赋值ES6 允许按照一一对应的方式从数组或对象中提取值再赋值给变量。解构 分解数据结构赋值 给变量赋值。7.1 数组的解构赋值按位置对应// ES6 之前 var a arr[0]; var b arr[1]; // ES6 之后 let [a, b, c] [1, 2, 3];未匹配到值时多余的变量被赋值为undefined左边允许有默认值如let [foo true] []输出trueundefined相当于没有值会触发默认值null是有值但值为 nulllet [a, b qianguyihao] [千古壹号, undefined]; // b 采用默认值 let [a, b qianguyihao] [千古壹号, null]; // b 为 null7.2 对象的解构赋值按属性名对应与数组按位置取值不同对象没有次序是根据键来取值的const person { name: qianguyihao, age: 28, sex: 男 }; let { name, age, sex } person; // 对象解构赋值未匹配到时变量为undefined可以给左边的变量自定义命名let { name: myName, age: myAge } person;此时等号左边的name、age是对应右边对象的属性名myName、myAge才是新定义的变量名若变量在解构前已定义需要给整个解构语句加圆括号({ foo } { foo: smyhvae });。7.3 字符串解构字符串会被转换成一个类似数组的对象因此也可以解构const [a, b, c, d] hello; console.log(a); // h console.log(typeof a); // string完整讲解见 05-ES6变量的解构赋值。八、ES6 模块化export 与 import8.1 为什么要模块化原生 JS 开发存在两大弊端而 Node.js 通过模块化开发很好地避免了这两个问题文件依赖如 a 文件依赖 b 文件、b 文件依赖 c 文件需要人工维护和人为分析依赖关系Node.js 中不需要命名冲突js 各个文件相互开放容易导致命名冲突Node.js 属于半封闭状态可以指定哪些内容开放、哪些内容封闭。软件开发中的模块化开发理念一个功能就是一个模块多个模块组成完整应用抽离一个模块不影响其他功能的运行。Node.js 规定一个 JS 文件就是一个模块模块内部定义的变量和函数默认情况下外部无法访问模块内部使用exports对象进行成员导出使用require方法导入其他模块详见 04-Node.js模块化规范CommonJS。而 ES6 模块化使用export导出、import引入语法如下export // 导出模块 import xxx from 路径 // 引入模块依赖模块需要编译打包处理原因有二有些浏览器不支持 ES6 语法写完 ES6 代码后需要通过Babel将 ES6 转化为 ES5生成 ES5 之后里面仍有require语法而浏览器不认识require关键字此时需要用Browserify编译打包 js进行再次转换。8.2 实战自定义模块Babel Browserify 全流程1初始化项目在工程文件中新建如下目录js | src | module1.js | module2.js | module3.js | module4.js | main.js index.html在工程根目录新建package.json{ name: es6-babel-browserify, version: 1.0.0 }2环境配置安装 babel 和 browserifynpm install babel-cli -g npm install babel-preset-es2015 --save-dev npm install browserify -g安装 Babel 的详细解释见 ES5和ES6的介绍。在根目录新建.babelrc{ presets: [ es2015 ], plugins: [] }3编写代码。module1.js ——分别暴露// 暴露模块采用分别暴露的方式 export function foo1() { console.log(我是 module1 中的 foo1); } export function foo2() { console.log(我是 module2 中的 foo2); } export let arr [1, 2, 3, 4, 5];module2.js ——统一暴露// 暴露模块采用统一暴露的方式 function fn1() { console.log(我是 module2 中的 fn1); } function fn2() { console.log(我是 module2 中的 fn2); } // 统一暴露 export { fn1, fn2 };module3.js ——默认暴露暴露箭头函数// 暴露模块采用默认暴露的方式 // 语法格式export default value; export default () { console.log(我是 module3 中 default 方式暴露的函数); };module4.js ——默认暴露多个属性包成对象// 暴露模块采用默认暴露的方式 // 语法格式export default value; export default { name: 我是 module4 中 default 方式暴露的属性 name, foo() { console.log(我是 module4 中 default 方式暴露的函数 foo); } };关于默认暴露的两点说明只能写一次 default即一个模块只能进行一次默认暴露如果想暴露多个属性或方法把所有内容包成一个对象放进 default 里即可如 module4.js 所示。main.js ——主模块引入上面四个模块// 主模块。引入其他的模块 import { foo1, foo2 } from ./module1; // 解构赋值导入括号里的名字要和 module1 中的导出名一致 import { fn1, fn2 } from ./module2; // 解构赋值导入名字要和 module2 中的导出名一致 import myModule3 from ./module3; // default 方式暴露模块名随便起 import myModule4 from ./module4; // default 方式暴露模块名随便起 // 调用 module1、module2 中的内容 foo1(); foo2(); fn1(); fn2(); // 调用 module3 中的内容 myModule3(); // 调用 module4 中的内容 console.log(myModule4.name); // module4 中的属性 myModule4.foo(); // module4 中的方法关键区别重要module1 和 module2 采用常规暴露分别暴露 / 统一暴露引入时模块名要一致且必须用对象解构赋值的形式import { xxx } from ...不能用import myModule from ...这种形式否则会得到 undefinedmodule3 和 module4 采用默认暴露export default引入时模块名随便起。index.html —— 引入编译产物dist/main.js!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta http-equivX-UA-Compatible contentieedge titleDocument/title /head body script srcdist/main.js/script /body /html4编译转换。如果不转换而直接加载js/src/main.js浏览器会报错。转换分两步第一步用 Babel 将 ES6 转换为 ES5babel src -d build # build 目录会自动生成含义将src目录下所有 ES6 文件转化为 ES5 文件并放在build目录下。转换后发现直接加载build目录下的 ES5 文件仍会报错因为浏览器不认识main.js里的require关键字。第二步用 Browserify 编译打包build目录下的 ES5 文件browserify build/main.js -o dist/main.js # dist 目录需要手动创建dist/main.js就是需要引入到 index.html 里的文件。此后每次修改完 ES6 代码都要重新执行上述两个命令生成新的 js 文件。完整工程案例可参照仓库中的 JavaScript模块化ES6。8.3 实战引入第三方模块以 jQuery 为例下载 jQuery 1.X 版本中最新版npm install jquery1在 main.js 中引入import $ from jQuery;之后就可以通过$符号正常书写 jQuery 代码了。九、延伸阅读04-ES6变量 let、const 和块级作用域块级作用域、for 循环面试题、暂时性死区的完整讲解06-ES6箭头函数箭头函数语法与 this 指向详解07-剩余参数和扩展运算符剩余参数、展开运算符的更多应用场景05-ES6变量的解构赋值数组、对象、字符串解构的完整规则08-字符串、数组、对象的扩展includes、startsWith、endsWith、repeat、Number 扩展、Object.is 等JavaScript模块化ES6ES6 模块化的完整实战04-Node.js模块化规范CommonJSNode.js 中 exports / require 的模块机制。在实际开发中建议以let/const替代var减少全局污染用模板字符串、箭头函数和解构赋值提升代码可读性再结合 Babel 等工具将 ES6 代码编译为兼容低端浏览器的 ES5即可在企业级项目中放心使用 ES6 语法。赞分享文档教程前端【免费下载链接】Web千古前端图文教程超详细的前端入门到进阶知识库。从零开始学前端做一名精致优雅的前端工程师。项目地址https://gitcode.com/gh_mirrors/we/Web点击查看免费下载相关推荐千古前端图文教程CSS3 边框与圆角实战汇总——27 种图形与纯 CSS 爱心的完整实现千古前端图文教程CSS3 边框与圆角实战汇总——27 种图形与纯 CSS 爱心的完整实现 导读 本篇文章是《千古前端图文教程》中 CSS3 边框知识的实战总结文档教程前端千古前端图文教程ES6 箭头函数与参数默认值详解千古前端图文教程ES6 箭头函数与参数默认值详解 导读本文出自「千古前端图文教程」的 ES6 语法专题围绕箭头函数的 定义语法、简化写法、this 指向文档教程前端千古前端图文教程JavaScript 面向对象简介OOP、原型与 ES6 Class千古前端图文教程JavaScript 面向对象简介OOP、原型与 ES6 Class 导读 本文是「千古前端图文教程」中《27 面向对象简介》一文的完整展文档教程前端上一篇PUBG地图黑客团队协作应用小队共享地图实战技巧下一篇从 CartPole 到 Mountain CarML-For-Beginners 强化学习篇的 Q-Learning 环境迁移实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考