ES6_新特性
let
let关键字用来声明变量,使用 let声明的变量有几个特点:
1) 不允许重复声明
2) 块级作用域
3) 不存在变量提升
4) 不影响作用域链
<script> //声明变量 let a; let b,c,d; let e = 100; let f = 521, g = 'iloveyou', h = []; //1. 变量不能重复声明 // let star = '罗志祥'; // let star = '小猪'; //2. 块级作用域 全局, 函数, eval // if else while for // { // let girl = '周扬青'; // } // console.log(girl); //3. 不存在变量提升 // console.log(song); // let song = '恋爱达人'; //4. 不影响作用域链 { let school = '清华'; function fn(){ console.log(school); } fn(); } </script>
经典案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>点击 DIV 换色</title> <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <style> .item { width: 100px; height: 50px; border: solid 1px rgb(42, 156, 156); float: left; margin-right: 10px; } </style> </head> <body> <div class="container"> <h2 class="page-header">点击切换颜色</h2> <div class="item"></div> <div class="item"></div> <div class="item"></div> </div> <script> //获取div元素对象 let items = document.getElementsByClassName('item') //遍历并绑定事件 for (let i = 0; i < items.length; i++) { items[i].onclick = function () { //修改当前元素的背景颜色 // this.style.background = 'pink'; items[i].style.background = 'pink' } } </script> </body> </html>
const
const 关键字用来声明常量, const声明有以下特点
1) 声明必须赋初始值
2) 标识符一般为大写
3) 不允许重复声明
4) 值不允许修改
5) 块级作用域
注意:对象属性修改和数组元素变化不会触发const错误
应用场景:声明对象类型使用const,非对象类型声明选择 let
<script> //声明常量 const SCHOOL = '清华'; //1. 一定要赋初始值 // const A; //2. 一般常量使用大写(潜规则) // const a = 100; //3. 常量的值不能修改 // SCHOOL = 'QINGHUA'; //4. 块儿级作用域 // { // const PLAYER = 'UZI'; // } // console.log(PLAYER); //5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错 const TEAM = ['UZI','MXLG','Ming','Letme']; // TEAM.push('Meiko'); </script>
变量的解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
<script> //1. 数组的结构 // const F4 = ['小沈阳','刘能','赵四','宋小宝']; // let [xiao, liu, zhao, song] = F4; // console.log(xiao); // console.log(liu); // console.log(zhao); // console.log(song); //2. 对象的解构 // const zhao = { // name: '赵本山', // age: '不详', // xiaopin: function(){ // console.log("我可以演小品"); // } // }; // let {name, age, xiaopin} = zhao; // console.log(name); // console.log(age); // console.log(xiaopin); // xiaopin(); </script>
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识 ,
特点:
1) 字符串中可以出现换行符
2) 可以使用 ${xxx} 形式输出变量
注意:当遇到字符串与变量拼接的情况可以使用模板字符串
<script> //1. 声明 // let str = `我也是一个字符串哦!`; // console.log(str, typeof str); //2. 内容中可以直接出现换行符 let str = `<ul> <li>沈腾</li> <li>玛丽</li> <li>魏翔</li> <li>艾伦</li> </ul>`; //3. 变量拼接 let lovest = '魏翔'; let out = `${lovest}是我心目中最搞笑的演员!!`; console.log(out); </script>
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
<script> let name = '新东方'; let change = function(){ console.log('我们可以改变你!!'); } const school = { name, change, improve(){ console.log("我们可以提高你的技能"); } } console.log(school); </script>
箭头函数
ES6 允许使用 「 箭头 」(=>)定义函数。
注意点:
1) 如果形参只有一个,则小括号可以省略
2) 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
3) 箭头函数this指向声明时所在作用域下this 的值
4) 箭头函数不能作为构造函数实例化
5) 不能使用arguments
注意:箭头函数不会更改this指向,用来指定回调函数会非常合适
<script> //声明一个函数 // let fn = function(){ } // let fn = (a,b) => { // return a + b; // } //调用函数 // let result = fn(1, 2); // console.log(result); //1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值 function getName(){ console.log(this.name); } let getName2 = () => { console.log(this.name); } //设置 window 对象的 name 属性 window.name = '新东方'; const school = { name: "XINDONGFANG" } //直接调用 // getName(); // getName2(); //call 方法调用 // getName.call(school); // getName2.call(school); //2. 不能作为构造实例化对象 // let Person = (name, age) => { // this.name = name; // this.age = age; // } // let me = new Person('xiao',30); // console.log(me); //3. 不能使用 arguments 变量 // let fn = () => { // console.log(arguments); // } // fn(1,2,3); //4. 箭头函数的简写 //1) 省略小括号, 当形参有且只有一个的时候 // let add = n => { // return n + n; // } // console.log(add(9)); //2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略 // 而且语句的执行结果就是函数的返回值 let pow = n => n * n; console.log(pow(8)); </script>
经典案例
<script> //需求-1 点击 div 2s 后颜色变成『粉色』 //获取元素 let ad = document.getElementById('ad'); //绑定事件 ad.addEventListener("click", function(){ //保存 this 的值 // let _this = this; //定时器 setTimeout(() => { //修改背景颜色 this // console.log(this); // _this.style.background = 'pink'; this.style.background = 'pink'; }, 2000); }); //需求-2 从数组中返回偶数的元素 const arr = [1,6,9,10,100,25]; // const result = arr.filter(function(item){ // if(item % 2 === 0){ // return true; // }else{ // return false; // } // }); const result = arr.filter(item => item % 2 === 0); console.log(result); // 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调 // 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法 </script>
参数默认值
<script> //1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则) // function add(a,c=10,b) { // return a + b + c; // } // let result = add(1,2); // console.log(result); //2. 与解构赋值结合 function connect({host="127.0.0.1", username,password, port}){ console.log(host) console.log(username) console.log(password) console.log(port) } connect({ host: 'baidu.com', username: 'root', password: 'root', port: 3306 }) </script>
rest参数
ES6引入rest参数,用于获取 函数的实参,用来代替 arguments。
注意:rest参数非常适合不定个数参数函数的场景
<script> // ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments // ES5 获取实参的方式 // function date(){ // console.log(arguments); // } // date('白芷','阿娇','思慧'); // rest 参数 // function date(...args){ // console.log(args);// filter some every map // } // date('阿娇','柏芝','思慧'); // rest 参数必须要放到参数最后 function fn(a, b, ...args) { console.log(a); console.log(b); console.log(args); } fn(1, 2, 3, 4, 5, 6); </script>
扩展运算符
扩展运算符(spread)也是三个点 (...)。
它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
<script> // 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』 //声明一个数组 ... const tfboys = ['易烊千玺','王源','王俊凯']; // => '易烊千玺','王源','王俊凯' // 声明一个函数 function chunwan(){ console.log(arguments); } chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯') </script>
经典案例
<script> //1. 数组的合并 情圣 误杀 唐探 // const kuaizi = ['王太利','肖央']; // const fenghuang = ['曾毅','玲花']; // // const zuixuanxiaopingguo = kuaizi.concat(fenghuang); // const zuixuanxiaopingguo = [...kuaizi, ...fenghuang]; // console.log(zuixuanxiaopingguo); //2. 数组的克隆 // const sanzhihua = ['E','G','M']; // const sanyecao = [...sanzhihua];// ['E','G','M'] // console.log(sanyecao); //3. 将伪数组转为真正的数组 const divs = document.querySelectorAll('div'); const divArr = [...divs]; console.log(divArr);// arguments </script>
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
1) ES6创造了一种新的遍历命令 for...of循环, Iterator接口主要供 for...of消费
2) 原生具备 iterator接口的数据 (可用 for of遍历 )
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
3) 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next方法返回一个包含 value和 done属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
案例可在我的另一篇文章《ES6_Symbol》的Symbol.iterator模块查看。
生成器
生成器函数是 ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
代码说明:
1) * 的位置没有限制
2) 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next方法可以得到yield语句后的值
3) yield相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
4) next方法可以传递实参,作为 yield语句的返回值
生成器函数
<script> //生成器其实就是一个特殊的函数 //异步编程 纯回调函数 node fs ajax mongodb //函数代码的分隔符 function* gen() { console.log(111); yield '一只没有耳朵'; console.log(222); yield '一只没有尾部'; console.log(333); yield '真奇怪'; console.log(444); } // let iterator = gen(); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); //遍历 for (let v of gen()) { console.log(v); } </script>
生成器函数参数
<script> function* gen(arg) { console.log(arg); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three); } //执行获取迭代器对象 let iterator = gen('AAA'); console.log(iterator.next()); //next方法可以传入实参 console.log(iterator.next('BBB')); console.log(iterator.next('CCC')); console.log(iterator.next('DDD')); </script>
生成器函数实例
<script> //模拟获取 用户数据 订单数据 商品数据 function getUsers() { setTimeout(() => { let data = '用户数据'; //调用 next 方法, 并且将数据传入 iterator.next(data); }, 1000); } function getOrders() { setTimeout(() => { let data = '订单数据'; iterator.next(data); }, 1000) } function getGoods() { setTimeout(() => { let data = '商品数据'; iterator.next(data); }, 1000) } function* gen() { let users = yield getUsers(); console.log(users); let orders = yield getOrders(); console.log(orders); let goods = yield getGoods(); console.log(goods); } //调用生成器函数 let iterator = gen(); iterator.next(); </script>
Set
ES6 提供了新的数据结构 Set(集合) 。它类似于数组,但成员的值都是唯一的 ,集合实现了 iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历,集合的属性和方法:
1) size返回集合的元素个数
2) add增加一个新元素,返回当前集合
3) delete删除元素,返回 boolean 值
4) has检测集合中是否包含某个元素,返回 boolean值
5) clear清空集合,返回 undefined
<script> //声明一个 set let s = new Set(); let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']); //元素个数 // console.log(s2.size); //添加新的元素 // s2.add('喜事儿'); //删除元素 // s2.delete('坏事儿'); //检测 // console.log(s2.has('糟心事')); //清空 // s2.clear(); // console.log(s2); for(let v of s2){ console.log(v); } </script>
经典案例
<script> let arr = [1,2,3,4,5,4,3,2,1]; //1. 数组去重 // let result = [...new Set(arr)]; // console.log(result); //2. 交集 let arr2 = [4,5,6,5,6]; // let result = [...new Set(arr)].filter(item => { // let s2 = new Set(arr2);// 4 5 6 // if(s2.has(item)){ // return true; // }else{ // return false; // } // }); // let result = [...new Set(arr)].filter(item => new Set(arr2).has(item)); // console.log(result); //3. 并集 // let union = [...new Set([...arr, ...arr2])]; // console.log(union); //4. 差集 let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item))); console.log(diff); </script>
Map
ES6 提供了 Map 数据结构。
它类似于对象,也是键值对的集合。
但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map也实现了iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历。
Map的属性和方法:
1) size 返回 Map的元素个数
2) set 增加一个新元素,返回当前 Map
3) get 返回键名对象的键值
4) has 检测 Map中是否包含某个元素,返回 boolean值
5) clear 清空集合,返回 undefined
<script> //声明 Map let m = new Map(); //添加元素 m.set('name','少林达摩院'); m.set('change', function(){ console.log("我们可以改变你!!"); }); let key = { school : 'SHAOLING' }; m.set(key, ['北京','上海','深圳']); //size // console.log(m.size); //删除 // m.delete('name'); //获取 // console.log(m.get('change')); // console.log(m.get(key)); //清空 // m.clear(); //遍历 for(let v of m){ console.log(v); } // console.log(m); </script>
class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。
通过 class关键字,可以定义类。
基本上, ES6 的 class可以看作只是一个语法糖,它的绝大部分功能, ES5 都可以做到,新的 class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
1) class声明类
2) constructor定义构造函数初始化
3) extends继承父类
4) super调用父级构造方法
5) static定义静态方法和属性
6) 父类方法可以重写
类声明
<script> //手机 function Phone(brand, price){ this.brand = brand; this.price = price; } //添加方法 Phone.prototype.call = function(){ console.log("我可以打电话!!"); } //实例化对象 let Huawei = new Phone('华为', 5999); Huawei.call(); console.log(Huawei); //class class Shouji{ //构造方法 名字不能修改 constructor(brand, price){ this.brand = brand; this.price = price; } //方法必须使用该语法, 不能使用 ES5 的对象完整形式 call(){ console.log("我可以打电话!!"); } } let onePlus = new Shouji("1+", 1999); console.log(onePlus); </script>
静态成员
<script> // function Phone(){ // } // Phone.name = '手机'; // Phone.change = function(){ // console.log("我可以改变世界"); // } // Phone.prototype.size = '5.5inch'; // let nokia = new Phone(); // console.log(nokia.name); // // nokia.change(); // console.log(nokia.size); class Phone { //静态属性 static name = '手机'; static change() { console.log("我可以改变世界"); } } let nokia = new Phone(); console.log(nokia.name); // undefined console.log(Phone.name); // 手机 </script>
构造函数继承及对父类方法重写
<script> class Phone { //构造方法 constructor(brand, price) { this.brand = brand; this.price = price; } //父类的成员属性 call() { console.log("我可以打电话!!"); } } class SmartPhone extends Phone { //构造方法 constructor(brand, price, color, size) { super(brand, price); // Phone.call(this, brand, price) this.color = color; this.size = size; } photo() { console.log("拍照"); } playGame() { console.log("玩游戏"); } call() { console.log('我可以进行视频通话'); } } const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch'); console.log(xiaomi); xiaomi.call(); xiaomi.photo(); xiaomi.playGame(); </script>
class的set-get
<script> // get 和 set class Phone{ get price(){ console.log("价格属性被读取了"); return 'iloveyou'; } set price(newVal){ console.log('价格属性被修改了'); } } //实例化对象 let s = new Phone(); // console.log(s.price); </script>
数值扩展
1.Number.EPSILON 是 JavaScript 表示的最小精度
2.二进制和八进制:ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b和 0o表示。
3.Number.isFinite 检测一个数值是否为有限数
4.Number.isNaN 检测一个数值是否为 NaN
5.Number.parseInt Number.parseFloat字符串转整数
6.Number.isInteger 判断一个数是否为整数
7.Math.trunc 将数字的小数部分抹掉
<script> //0. Number.EPSILON 是 JavaScript 表示的最小精度 //EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16 // function equal(a, b){ // if(Math.abs(a-b) < Number.EPSILON){ // return true; // }else{ // return false; // } // } // console.log(0.1 + 0.2 === 0.3); // console.log(equal(0.1 + 0.2, 0.3)) //1. 二进制和八进制 // let b = 0b1010; // let o = 0o777; // let d = 100; // let x = 0xff; // console.log(x); //2. Number.isFinite 检测一个数值是否为有限数 // console.log(Number.isFinite(100)); // console.log(Number.isFinite(100/0)); // console.log(Number.isFinite(Infinity)); //3. Number.isNaN 检测一个数值是否为 NaN // console.log(Number.isNaN(123)); //4. Number.parseInt Number.parseFloat字符串转整数 // console.log(Number.parseInt('5211314love')); // console.log(Number.parseFloat('3.1415926神奇')); //5. Number.isInteger 判断一个数是否为整数 // console.log(Number.isInteger(5)); // console.log(Number.isInteger(2.5)); //6. Math.trunc 将数字的小数部分抹掉 // console.log(Math.trunc(3.5)); //7. Math.sign 判断一个数到底为正数 负数 还是零 console.log(Math.sign(100)); console.log(Math.sign(0)); console.log(Math.sign(-20000)); </script>
对象方法扩展
ES6新增了一些 Object对象的方法
1) Object.is 比较两个值是否严格相等,与『 ===』行为基本一致(+0 与 NaN)
2) Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
3) __proto__、 setPrototypeOf、 setPrototypeOf可以直接设置对象的原型
<script> //1. Object.is 判断两个值是否完全相等 // console.log(Object.is(120, 120));// === // console.log(Object.is(NaN, NaN));// === // console.log(NaN === NaN);// === //2. Object.assign 对象的合并 // const config1 = { // host: 'localhost', // port: 3306, // name: 'root', // pass: 'root', // test: 'test' // }; // const config2 = { // host: 'http://atguigu.com', // port: 33060, // name: 'atguigu.com', // pass: 'iloveyou', // test2: 'test2' // } // console.log(Object.assign(config1, config2)); //3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof const school = { name: '少林达摩院' } const cities = { xiaoqu: ['北京','上海','深圳'] } Object.setPrototypeOf(school, cities); console.log(Object.getPrototypeOf(school)); console.log(school); </script>
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势:
1) 防止命名冲突
2) 代码复用
3) 高维护性
ES6之前的模块化规范有
1) CommonJS => NodeJS、 Browserify
2) AMD => requireJS
3) CMD => seaJS
模块功能主要由两个命令构成:export和 import。
export命令用于规定模块的对外接口
import命令用于输入其他模块提供的功能
m1.js
//分别暴露
export let school = '少林达摩院';
export function teach() {
console.log("我们可以教给你绝世神功");
}
m2.js
//统一暴露
let school = '少林达摩院';
function findJob(){
console.log("我们可以帮助你学会化缘!!");
}
export {school, findJob};
m3.js
//默认暴露
export default {
school: '少林达摩院',
change: function(){
console.log("我们可以改变你!!");
}
}
app.js
//入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
// console.log(m1);
// console.log(m2);
// console.log(m3);
// m1.teach();
// m2.findJob();
// m3.default.change();
//修改背景颜色为粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ES6 模块化</title> </head> <body> <script type="module"> //1. 通用的导入方式 //引入 m1.js 模块内容 // import * as m1 from "./src/js/m1.js"; // //引入 m2.js 模块内容 // import * as m2 from "./src/js/m2.js"; // //引入 m3.js // import * as m3 from "./src/js/m3.js"; //2. 解构赋值形式 // import {school, teach} from "./src/js/m1.js"; // import {school as guigu, findJob} from "./src/js/m2.js"; // import {default as m3} from "./src/js/m3.js"; //3. 简便形式 针对默认暴露 // import m3 from "./src/js/m3.js"; // console.log(m3); </script> <script src="./src/js/app.js" type="module"></script> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本