ES6~ES11
一、ECMASript 6 新特性
let 关键字
- let 关键字用来声明变量,用来 let 声明的变量有几个特点:
1、不允许重复声明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5A3oAfNe-1678617402356)(D:\01_Software\03-markdownImages\image-20230115094535324.png)]
2、块级作用域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IE1iv8Ap-1678617402357)(D:\01_Software\03-markdownImages\image-20230115094554126.png)]
3、不存在变量提升
4、不影响作用域链
//1、不允许重复声明
let start = "罗志祥";
let start = "小猪";
//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();
}
应用场景:以后声明变量使用 let 就对了
let items = document.querySelectAll(".item");
for(let i = 0; i < items.length; i++){
items[i].addEventListener("click",function(){
items[i].style.background = "pink";
})
}
const 定义常量
1、一定要付初始值
2、潜规则:一般常量使用大写
3、常量值不能修改
4、块级作用域
变量的解构赋值
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} = zhao;
console.log(name);
console.log(age);
let {xiaopin} = zhao;
xiaopin();
模板字符串
1、可以直接出现换行符
let str = `<ul>
<li>刘翔</li>
<li>苏炳添</li>
</ul>`;
2、变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最喜欢的演员`;
简化对象写法
旧版本
var school = {
name: '沈腾',
xiaopin: function(){
console.log('小品');
}
}
新版本
- 如果外部变量跟内部变量的名称一样则可以直接省略
let name = 'summer';
let change = function(){
console.log("alksdjflkajds");
}
let hahah = {
name,
change,
improve(){
console.log("klajsdfkljjhadsf");
}
}
箭头函数
1、this 是静态的:this 始终指向函数声明时所在作用域下的 this 的数值
- call 方法可以修改 this 的指向
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
window.name = '尚硅谷';
const school = {
name: "ATGUIGU"
}
//直接调用
getName();
getName2();
//结果:
尚硅谷
尚硅谷
//call 方法调用
getName.call(school);
getName2.call(school);
//结果:
ATGUIGU
尚硅谷
2、不能作为构造实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiaoming', 30);
console.log(me);
3、不能使用 arguments 变量
4、箭头函数的简写
- 省略小括号,当形参有且只有一个的时候
- 省略花括号,当代码只有一条代码的时候
//1) 省略小括号
let add = n => {
return n + n;
}
console.log(add(9))
//2)省略花括号
let add = n => return n * n;
console.log(add(9));
应用场景
1、点击 div 2s 后颜色变成粉色
错误示范:定时器的this是指向window的
var div = document.querySelect("div");
div.addEventListener('click',function(){
Interview(function(){
this.style.background = 'pink';
},2000)
})
1)正确示范:保存this
var div = document.querySelect("div");
div.addEventListener('click',function(){
let _this = this;
Interview(function(){
_this.style.background = 'pink';
},2000)
})
2)正确示范:箭头函数
- 它是指向声明时所在作用域下的 this 数值
var div = document.querySelect("div");
div.addEventListener('click',function(){
Interview(() => {
this.style.background = 'pink';
},2000)
})
2、从数组中返回偶数的元素
旧版本
const arr = [1,6,8,9,6,4,3];
const result = arr.filter(function(item){
if(item % 2 === 0){
return true;
}else{
return fasle;
}
})
新版本
const arr = [1,6,8,9,6,4,3];
const result = arr.filter(item => item % 2 === 0);
形参初始值
1、形参初始值 具有默认的参数,一般位置要靠后(潜规则)
function add(a,b,c = 10){
return a + b + c;
}
let result = add(1,2);
console.log(result);
//13;
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: 'atguigu.com',
username: 'root',
password: 'root',
port: 3305
})
//atguigu.com
//root
//root
//3305
rest 形参
1、rest 参数必须要放参数最后面
2、rest 参数是以数组的方式返回的
function fn(a, b, ...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6)
扩展运算符
- 【…】 扩展运算符能将 【数组】转换为逗号分隔的【参数序列】
- 扩展运算符是放在实参里面的
const tfboys = ['易烊千玺', '王俊凯', '王源'];
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);
使用场景
1、数组的合并
const kuaizi = ['王太利', '小样'];
const fenghuang = ['曾毅', '菱花'];
//1、函数合并
const hebing = kuaizi.concat(fenghuang);
//2、第二种
const hebing = [...kuaizi, ...fenghuang];
2、数组的克隆
- 如果拷贝的元素有引用类型,则是浅拷贝
const sanzhihua = ['E', 'G', 'M'];
const sanyecao = [...sanzhihua];
console.log(sanyecao) //['E', 'G', 'M']
3、将伪数组转为真正的数组
const divs = document.querSeletorAll('div');
const divArr = [...divs];
console.log(divArr)
Symbol
- ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
-
Symbol 的值是唯一的,用来解决命名冲突的问题
-
Symbol 值不能与其他数据进行运算
-
Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可以使用Reflect.ownKeys 来获取对象的所有键名
七种数据类型(USONB)
1、u:undefined
2、s:string symbol
3、o:object
4、n:null number
5、b:boolean
//创建 symbol
let s = Symbol();
let s3 = Symbol('尚硅谷');
let s4 = Symbol('尚硅谷');
console.log(s2 === s3) // false
let s3 = Symbol.for('尚硅谷');
let s4 = Symbol.for('尚硅谷');
console.log(s2 === s3) // true
注:遇到唯一性的场景就要想到 Symbol
Symbol 创建对象属性
第一种方法
let game = {
up(){
console.log("up");
}
down(){
console.log("down")
}
}
//声明对象
let methods = {
up: Symbol();
down:Symbol();
}
//添加属性
game[methdos.up] = function(){
console.log("我可以改变形状");
}
game[methods.down] = function(){
console.log("我可以快速下降");
}
第二种方法
let youxi = {
name: "狼人杀",
[Symbol("say")]: function(){
console.log("天黑请闭眼")
},
[Symbol('zibao')]: function(){
console.log("我可以自爆");
}
}
Symbol 内置值
方法 | 说明 |
---|---|
Symbol.hasInstance | 当其他对象使用 instanceof 运算符,判断是否为该对 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个 |
Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会 |
Symbol.replace | 当该对象被 str.replace(myObject)方法调用时,会返回 |
Symbol.search | 当该对象被 str.search (myObject)方法调用时,会返回 |
Symbol.split | 当该对象被 str.split(myObject)方法调用时,会返回该 |
Symbol.iterator | 对象进行 for…of 循环时,会调用 Symbol.iterator 方法, |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返 |
Symbol. toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值 |
Symbol. unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除 |
//Symbol.hasInstance
class Person{
static [Symbol.hasInstance](param){
console.log(param);
console.log("我是被用来检查类型的");
return fasle;
}
}
let o = {};
console.log(o instanceof Person); // false
//Symbol.isConcatSpreadable
const arr = [1, 2, 3];
const arr2 = [4,5,6];
console.log(arr.concat(arr2)); // [1,2,3,4,5,6];
const arr = [1, 2, 3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2)); // [1,2,3,Array(3)];
迭代器
-
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
-
原生具备 iterator 接口的数据(可用 for of 遍历)
-
a) Array
-
b) Arguments
-
c) Set
-
d) Map
-
e) String
-
f) TypedArray
-
g) NodeList
- 工作原理
-
a) 创建一个指针对象,指向当前数据结构的起始位置
-
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
-
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
-
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
//声明一个数组
const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];
let iterator = xiyou[Symbol.iterator]();
console.log(iterator.nect());
console.log(iterator.nect());
console.log(iterator.nect());
console.log(iterator.nect());
console.log(iterator.nect());
自定义迭代器
const banji = {
name: "终极一般",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator](){
let intdex = 0;
let _this = this;
return {
next: function(){
if(index < _this.stus.length){
const result = {
value: _this.stus[i], done: false;
index++;
return result;
}else{
return {value: undefined, done: true}
}
}
}
};
}
}
生成器
代码说明:
-
*的位置没有限制
-
生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
-
yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
-
next 方法可以传递实参,作为 yield 语句的返回值
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
return '真奇怪';
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
生成器函数参数
function * gen(arg){
console.log(arg);
let one = yield '一只没有耳朵';
console.log(one);
let two = yield '一只没有尾巴';
console.log(two);
}
let iterator = gen('AAA');
console.log(iterator.next());
console.log(iterator.next('BBB'));
//结果
//AAA
//BBB
生成器实例(1)
- 实现异步任务的功能
旧版本
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
},3000)
},2000)
},1000)
新版本
function one(){
setTimeout(() => {
console.log(111);
iterator.next();
})
}
function two(){
setTimeout(() => {
console.log(222);
iterator.next();
})
}
function three(){
setTimeout(() => {
console.log(333);
iterator.next();
})
}
function * gen(){
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
生成器实例(2)
- 用户数据、订单数据、商品数据
function one(){
setTimeout(() => {
let data = "用户数据";
iterator.next(data);
})
}
function two(){
setTimeout(() => {
let data = "订单数据";
iterator.next(data);
})
}
function three(){
setTimeout(() => {
let data = "商品数据";
iterator.next(data);
})
}
function * gen(){
let one = yield one();
console.log(one);
yield two();
let two = console.log(two);
let three = yield three();
console.log(three);
}
let iterator = gen();
iterator.next();
Set 集合
- ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
- size
返回集合的元素个数
- add
增加一个新元素,返回当前集合
- delete
删除元素,返回 boolean 值
- has
检测集合中是否包含某个元素,返回 boolean 值
- clear
清空集合,返回 undefined
//声明变量
let s = new Set();
let s2 = new Set(['哈哈哈', '嘻嘻嘻'])
//遍历
for(var v of s2){
console.log(v);
}
使用场景
let arr = [1,2,3,4,5,6,7];
//1、去重
let result = [...new Set(arr)];
//2、交集
let arr2 = [4,5,6,7];
let result = [...new Set(arr)].filter(item => {
let ar2 = new Set(arr2);
if(ar2.has(item)){
return true;
}else{
return fasle;
}
})
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
//3、并集
let result = [...new Set([...arr, ...arr2])];
//4、差集
let result = [...new Set(arr)].filter(!item => new Set(arr2).has(item));
Map 集合
- ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
- size
返回 Map 的元素个数
- set
增加一个新元素,返回当前 Map
- get
返回键名对象的键值
- has
检测 Map 中是否包含某个元素,返回 boolean 值
- clear
清空集合,返回 undefined
Class 类
class Phone{
constructor(brand,price){
this brand = brand;
this.price = price;
}
call(){
console.log("正在拨打电话");
}
}
let onePlus = new Phone("1+",1999);
console.log(onePlus);
Class 静态成员
- 实例化对象和静态成员的属性是不相通的
//可以通过 Phone.prototype.call 给类添加静态成员变量
class Phone{
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia); // undefined
console.log(Phone.name) // 手机
Class 继承
class Phone {
constructor(brand, price){
this.brand = brand;
this.price = price;
}
call(){
console.log('我可以打电话哦');
}
}
class SmartPhone extends Phone {
constructor(brand, price, size, color){
super(brand, price);
this.size = size;
this.color = color;
}
phone(){
console.log("我是手机");
}
}
Class 重写
- 子类不能调用父类的成员方法的
class Phone {
constructor(brand, price){
this.brand = brand;
this.price = price;
}
call(){
console.log('我可以打电话哦');
}
}
class SmartPhone extends Phone {
constructor(brand, price, size, color){
super(brand, price);
this.size = size;
this.color = color;
}
phone(){
console.log("我是手机");
}
//重写
call(){
console.log("重写方法");
}
}
get 和 set
class Phone{
get price(){
return "i love you";
}
set price(newVal){
}
}
let s = new Phone();
s.price = "free";
数值扩展
1、Number.EPSILON 是 JavaScript 表示最小精度
function equal(a, b){
if(Math.abs(a - b) < Number.EPSILON){
return true;
}else{
return false;
}
}
2、二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
3、Number.isNaN 检测一个数值是否是 NaN
Number.isNaN(123);
//true;
4、Number.parseInt Number.parseFloat字符串整数
- 如果有字符串则直接截断
5、Number.isInteger 判断一个数是否是整数
6、Math.trunc 将数字的小数部门抹掉
7、Math.sign 如果为正数返回 1 如果是负数返回 -1 如果是零返回 0
8、Number.isFinite 检查一个数值是否为有限数
对象方法扩展
1、Object.is 判断两个数值是否完全相等(类似全等)
console.log(123 === 123); // true
console.log(Object.is(123,123)) // true
console.log(NaN === NaN) // false;
console.log(Object.is(NaN, NaN)) // true;
2、Object.assign 对象的合并
- 会将 config1 没有属性的追加
- 如果参数重属性,以 config1 为准
const config1 = {
host: 'localhost',
prot: 3306,
name: 'root',
pass: 'root'
};
const config2 = {
host: 'localhost',
prot: 3306,
name: 'root',
pass: 'root',
test: 'asdf'
}
3、Object.setPrototypeOf、Object.getPrototypeOf
- 设置原型,设置对象
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京', '深圳']
}
Object.setPrototypeOf(school, cities);
模块化
引入模块数据方式一
1、模块化的好处
模块化的优势有以下几点:
-
防止命名冲突
-
代码复用
-
高维护性
2、模块化规范产品
ES6 之前的模块化规范有:
-
CommonJS => NodeJS、Browserify
-
AMD => requireJS
-
CMD => seaJS
3、ES6模块化语法
模块功能主要由两个命令构成:export 和 import。
-
export 命令用于规定模块的对外接口
-
import 命令用于输入其他模块提供的功能
m1.js
export let school = '尚硅谷';
export function teach() {
console.log("我们可以教你开发技能");
}
m2.js
let school = '尚硅谷';
function teach() {
console.log("我们可以教你开发技能");
}
export {school, teach};
m2.js
export default {
school: 'atguigu',
change: function(){
console.log("我们可以改变你")
}
}
index.html
<script type = "module">
//1、通用的导入方式
import * as m1 from "./src/js/m1.js";
import * as m2 from "./src/js/m2.js";
import * as m3 from "./src/js/m3.js";
m3.default.change();
//2、解构赋值的形式
import {school, teach} from "./src/js/m1.js";
import {school as guigu, teach} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js"
//3、渐变形式 针对默认暴露
import m3 from "./src/js/m3.js";
</script>
引入模块数据方式二
app.js
//模块引入
import * as m1 from "./m1.js";
import * as m1 from "./m2.js";
import * as m1 from "./m3.js";
index.html
<script src="./src/js/app.js" type="module"></script>
bable对ES6模块化代码转换
1、初始化 npm init —yes
2、开发依赖 npm i babel-cli babel-preset-env browserify -D
3、npx babel src/js -d dist/js --presets=babel-preset-env
4、打包 npx browserify dist/js/app.js -o dist/bundle.js
引入NPM包
1、安装 jquery 包:npm i jquery
import $ from 'jquery';
${'body'}.css('background,''pink');
og(“我们可以改变你”)
}
}
**index.html**
```html
<script type = "module">
//1、通用的导入方式
import * as m1 from "./src/js/m1.js";
import * as m2 from "./src/js/m2.js";
import * as m3 from "./src/js/m3.js";
m3.default.change();
//2、解构赋值的形式
import {school, teach} from "./src/js/m1.js";
import {school as guigu, teach} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js"
//3、渐变形式 针对默认暴露
import m3 from "./src/js/m3.js";
</script>
引入模块数据方式二
app.js
//模块引入
import * as m1 from "./m1.js";
import * as m1 from "./m2.js";
import * as m1 from "./m3.js";
index.html
<script src="./src/js/app.js" type="module"></script>
bable对ES6模块化代码转换
1、初始化 npm init —yes
2、开发依赖 npm i babel-cli babel-preset-env browserify -D
3、npx babel src/js -d dist/js --presets=babel-preset-env
4、打包 npx browserify dist/js/app.js -o dist/bundle.js
引入NPM包
1、安装 jquery 包:npm i jquery
import $ from 'jquery';
${'body'}.css('background,''pink');