ES6简介
ECMAScript 6
- ECMAScript 是语言的标准
- 6是版本号
- ES6 = ECMAScript 这门语言的第六代标准
- ECMAScript = 语法 + API
ES与Javascript的关系
- Javascript(浏览器端)= ECMAScript (语法+API) + DOM + BOM
ES的兼容性
- 主流浏览器几乎都支持ES6
- IE老版本等不支持的浏览器,可以用Babel转码
let和const是什么
为什么需要const
- const就是为了一些初始化后就不希望改变的属性
const的注意事项
- 使用const声明常量,一旦声明,就必须立即初始化,不能留到以后赋值
- const声明常量,允许在不重新赋值的情况下修改它的值
let、const与var的区别
重复声明
- 已存在的变量,又声明一遍 var允许重复声明,let、const不允许
变量提升
- var会提升变量的声明到当前作用域的顶部
- let和const不存在变量提升
暂时性死区
- 只要作用域内存在let、const,它们所声明的变量或常量就自动“绑定”这个区域,不在受到尾部作用域的影响
window对象的属性和方法
-
在全局作用域中,var声明的变量,通过function声明的函数,会自动变成window对象的属性或方法
-
let 和 const 不会
块级作用域
什么是块级作用域
- var没有块级作用域
- let/const有块级作用域
作用域链
- 内层 -》 外层-》… -》 全局
有哪些块级作用域
- {}
- for(){}
- while(){}
- do{}while()
- if(){}
- switch(){}
- 函数作用域 function(){}
- 对象中的{}不构成作用域
模板字符串
- 表示
模板字符串与一般字符串的区别
- 一般字符串使用 + 好拼接变量
- 模板字符串 使用${变量}
- 输出多行字符串使用\n 也可以直接回车换行
- 输出 `和\等特殊字符
- ` hello ${world}`
模板字符串的注入
- 模板字符串可以注入变量
- 对象属性
- 函数
- 运算
- 总而言之就是能得到一个值
箭头函数
认识箭头函数
箭头函数的结构
- const/let 函数名 = 参数 =》函数体
如何讲一般函数写成箭头函数
箭头函数的注意事项
单个参数
-
const add = x => { return x + 1; }
-
无参数或则多个参数()不能省略
-
单行函数体
-
const add = (x,y) => x + y;
-
单行函数体可以同时省略{}和return
-
多行函数体不能省略
单行对象
-
const add = (x,y) => { return { value: x + y; }; } const add = (x,y) => ({ value: x + y; })
-
返回单行函数在{}外面加上 ()浏览器会将他看成对象{}
this指向
全局作用域中的this指向
-
console.log(this); //window
一般函数(非箭头函数)中的this指向
-
'use strict';//标注为严格模式 function add(){ console.log(this); } //非严格模式下undefined->window add(); //严格模式下 add(); //undefined window.add();//window调用
-
只有在函数调用的时候this指向才确定,不调用的时候,不知道指向谁
-
this指向和函数在哪里调用没关系,只和谁在调用有关
-
dom的事件,this就是dom对象
-
构造函数中的this 就是指向这个对象
-
apply()和call()中的this指向window
-
数组中的this指向 数组本身
-
new 函数返回的对象 第一步创建一个{} 第二部this = {} 第三步值赋给this 最后返回this
箭头函数中的this指向
-
const calc = { add:() => { console.log(this); } } calc.add();//window /* 解析: 结合作用域链 箭头函数没有this 所以在calc中找this 因为对象的{}不构成作用域 所以最后this指向windwo */
-
箭头函数没有自己的this指向
-
`use strict`; //开启严格模式 const calc = { add:function(){ const adder = () =>{ console.log(this); }; adder(); } }; calc.add();//指向calc const addFn = calc.add; addFn(); //undefined -> window
不适合箭头函数的场景
作为构造函数
-
const Person = () => {} new Person(); // 箭头函数没有this指向 // 所以报错
需要使用arguments的时候
-
function add(){ console.log(arguments);//arguments [1,2] } add(1,2); //变成箭头函数 const add = () => console.log(arguments); add();//报错 因为 箭头函数中没有arguments //ES6中会剩余参数可以代替arguments子
例子
-
const timer = { time: 0, start: function(){ btn.addEventListener('click',function(){ setInterval(function(){ console.log(this);//这里的setInterval在非严格模式下undefined-》window对象 this.time++; result.innerHTML = this.time; },1000); },false) } } //用that 保存上下文的this 解决 const timer = { time: 0, start: function(){ let that = this; btn.addEventListener('click',function(){ setInterval(function(){ this = that; console.log(this);//这里的setInterval在非严格模式下undefined-》window对象 this.time++; result.innerHTML = this.time; },1000); },false) } } //用箭头函数解决这个问题 const timer = { time: 0, start: function(){ btn.addEventListener('click',() =>{ setInterval(() =>{ console.log(this);//这里的setInterval在非严格模式下undefined-》window对象 this.time++; result.innerHTML = this.time; },1000); },false) } } timer.satrt() //解析因为箭头函数没有自己的this //所以在第一个内层的箭头函数中会去上一个函数获取this对象 //但是上一个对象也是箭头函数没有this //所以在上面找到了timer对象作为this
解构赋值
认识解构赋值
-
//以前的写法 const arr = [1,2,3]; const a = arr[0]; const b = arr[1]; const c = arr[2]; //解构赋值 const [a,b,c] = [1,2,3]
解构赋值是什么
- 解析某一数据的结构,将外面想要的东西提取出来,赋值给变量或常量
数组的解构赋值的原理
模式(结构)匹配
[] = [1,2,3]
左右的结构一样都是数组
索引值相同的完成赋值
-
[a,b,c] = [1,2,3]
-
const [a,[,,b],c] = [1,[2,4,5],3] //获取1 5 3
数组结构赋值的默认值
默认值的基本用法
-
const [a,b] = []; //const [a,b] = [undefined,undefined] const [a = 1,b = 2] = []; //设置默认值
默认值生效条件
-
只有当一个数组成员严格等于(===)undefined时,对应的默认值才会生效
-
const [a=1,b=2] = [3,0] //a = 3 //b = 0 const [a=1,b=2] = [3,null] //a = 3 //b = null const [a=1,b=2] = [3] //a = 3 //b = 2
默认值表达式
-
如果默认值是表达式,默认值表达式是惰性求值的
-
const func = () => { console.log("我被执行了"); return 2; } const [x= func()] = [1]; console.log(x); // 1 //用到了才会去执行这个函数 const [x= func()] = []; console.log(x); // 2
常见的类数组的解构赋值
arguments
-
将arguments类数组可以看成数组去解构赋值
-
function func(){ const [a,b] = arguments; console.log(a,b); } func(1,2);
NodeList
-
const [p1,p2,p3] = document.querySelectorAll('p');
-
NodeList也可以使用数组的方式解构赋值
函数参数的解构赋值
-
const array = [1,2]; const add = arr => arr[0]+ arr[1]; //使用解构赋值 const add = ([x,y]) => x + y; add(array);
交换变量的值
-
let x = 1;let y = 2;let temp = x;x = y;y = temp;//解构的方式交换[x,y] = [y,x];
对象的解构赋值的原理
模式(结构)匹配
- {} = {}
属性名相同的完成赋值
const {'age':age,'username':username} = {username:'Alex',age:18};
- 属性名和变量相同可简写
const {age,username} = {username:'Alex',age:18};
- 可以通过这个取别名
const {'age':age,'username':name} = {username:'Alex',age:18};
对象结构赋值的注意事项
默认值的生效调剂
- 对象的属性值严格等于undefined的时候,对应的默认值才会生效
- 数组还是对象的默认值都使用等号
const {username = 'ZhangSan', age = 0} ={username:'alex'}
默认值表达式
- 如果默认值是表达式,默认值表达式是惰性求值的
将一个已声明的变量用于解构赋值
-
let x = 2; ({x} = {x:1})
-
如果一个已经声明的变量用于对象的解构赋值,整个赋值需要在圆括号中进行
可以取到继承得到属性
-
const {toString} = {}; console.log(toString);
对象解构赋值的应用
-
const logPersonInfo = ({username,age}) => {console.log(username,age)} logPersonInfo({username:'alex',age:18})
-
const obj { x:1, y:[2,3,4], z:{ a:5, b:6 } } const {y,y:[,yy]} = obj; //只取3 和数组
字符串的解构赋值
数组形式的解构赋值
-
const [a,b,,c] = 'hello'; console.log(a,b,c)//h e o
对象形式解构赋值
-
const { 0:a,1:b,length} = 'hello' console.log(a,b,length)//h e 5
数字和布尔值的解构赋值
-
const { a = 1 ,toString} = 123; const { b = 2 ,toString} = true; //右边转换为了包装类但是没有属性只有值所以取不到
-
先将等号右边的值转为对象
undefined 和 null的解构赋值
-
const {toString} = undefined; const {toString} = null; //都会报错
-
由于undefined 和 null 无法转为对象,所以对他们进行解构赋值,都会报错
属性和方法的简洁表示法
对象字面量是什么
实例化构造函数生成对象
-
const person = new Object(); person.age = 18; person.speak = function(){};
对象字面量
-
const person = { age:18, speak: function(){} }
属性的简洁表示法
-
const age = 18; const person = { // age:age age };
-
键名和变量或常量名一样的时候,可以只写一个
方法的简洁表示
-
const person = { // speak:function(){} speak(){} }
-
方法可以省略冒号和function关键字
方括号语法
方括号语法的用法
-
const prop = 'age'; const person = {}; //person.prop = 18; person[prop] = 18; const person = { [prop]:18 }; //方括号语法可以卸载对象字面量中
方括号中可以放什么
-
${}
-
[值或通过计算可以得到的(表达式)]
-
const prop = 'age'; const func = () => 'age2'; const person = { [prop]:18, [func()]:18, ['sex']:'male', ['sex' + '1']:'male' }
方括号语法和点语法的区别
- 点语法是方括号语法的特殊形式
- 点语法使用:属性名有数字、字母、下划线以及$构成,并且数字还不能打头的时候可以使用点语法
- 当你的属性或方法名是合法标识符时,可以使用点语法,其他情况下请使用方括号语法
函数参数的默认值
认识函数参数的默认值
- 调用函数的时候传参了,就用传递的参数;如果没传参,就用默认值
函数参数默认值的基本用法
-
//以前做法 const multiply = (x,y) => { if(typeof y === 'undefined') y = 1; return x * y; } //函数参数默认值 const multiply = (x,y=1) => { return x * y; }
函数参数默认值的注意事项
默认值的生效条件
-
不传递参数,或者明确的传递的undefined作为参数,只有这两种情况下,默认值才会生效
-
const multiply = (x,y=1) => { return x * y; } multiply(2,0); // 2 multiply(2,null); // 0 2*null null被看待成了0 multiply(2,undefined);//2
默认值表达式
- 如果默认值是表达式,默认值表达式是惰性求值的
设置默认值的小技巧
- 函数参数的默认值,最好从参数列表的右边开始设置默认值
函数参数默认值的应用
接受很多参数得到时候
-
const logUser = (username = 'ZhangSan',age = 0,sex = 'male') => console.log(username,age,sex);
接收一个对象作为参数
-
const logUser = options => console.log(options.username,options.age,optionssex); const logUser = ({username,age,sex}) => console.log(username,age,sex); const logUser = ({username= 'ZhangSan',age = 0,sex = 'male'} = {}) => console.log(username,age,sex);
剩余参数
认识剩余参数
-
const add = (x,y,z,...args) => {}
剩余参数的本质
-
const add = (x,y,...args) => { console.log(x,y,args); } add(1,2,3,4,5); // 1 2 [3,4,5]
-
剩余参数永远都是一个数组,即使没有值,也是空数组
箭头函数的剩余参数
- 箭头函数的参数部分即使只有一个剩余参数,也不能省略圆括号
使用剩余参数代替arguments获取实际参数
-
const add = function(){ console.log(arguments); } //箭头函数中没有arguments 使用过剩余参数代替 const add = (...args) => { console.log(args); } add(1,2);
剩余参数的位置
- 剩余参数只有是最后一个参数,之后不能在有其他参数,否则会报错
剩余参数的应用
-
const add = (...args) => { let sum = 0; for(let i=0;i<args.length;i++){ sum += args[i]; } return sum; }
与解构赋值结合使用
-
const [num,...agrs] = [1,2,3,4] // num 1 // agrs [2,3,4]
-
const func = ([num,..agrs]) => {} func([1,2,3])
-
const {x,y,...z} = { a:3, x:1, y:2, b:4 } //x 1 //y 2 //z {3,4} 剩余元素
展开运算符
认识展开运算符
-
[3,1,2] Math.min([3,1,2]) // 错误 Math.min(3,1,2) [3,1,2] => 3,1,2
数组展开运算符的基本用法
-
Math.min(...[3,1,2])
区分剩余参数和展开运算符
根本区别
-
//展开运算符 // [3,1,2] => 3,1,2 //剩余参数 // 3,1,2 => [3,1,2]
-
他们的操作刚好相反
区分剩余参数和展开运算符
-
const add = (...agrs) => { console.log(args); // [1,2,3] console.log(...args); //1 2 3 } add(1,2,3)
-
consloe.log([...[1,2,3],4]) // [1,2,3,4]
数组展开运算符的应用
复制数组
-
const a = [1,2] const c = [...a]
合并数组
-
const a = [1,2] const b = [3] const c = [4,5] d = [0,...a,...b,...c] //d [0,1,2,3,4,5]
字符串转为数组
-
字符串也可按照数组的形式展开
-
arr = [...'hello']; // arr ["h","e","l","l","o"]
常见的类数组转化为数组
arguments
function func(){
console.log([...argument])
}
NodeList
let nodeList = [...document.querySelectorAll('p')];
对象展开运算符
展开对象
- 对象不能直接展开,必须在{}中展开
- 对象的展开:把属性罗列出来,用逗号分隔,方法一个{}中,构成新的对象
const apple = {
color:'红色',
shape:'球形',
taste:'甜'
};
console.log({...apple})
合并对象
const apple = {
color:'红色',
shape:'球形',
taste:'甜'
};
const pen = {
color:'黑色',
shape:'圆柱形',
use:'写字'
};
console.log({...apple,...pen})
/*
会拥有所有属性 属性名相同的会被后者覆盖
{
color:'黑色',
shape:'圆柱形',
taste:'甜',
use:'写字'
}
*/
注意事项
空对象的展开
- 如果展开一个空对象,则没有任何效果
非对象的展开
- 如果展开的不是对象,则会自动将其转为对象,在将其属性罗列出来
- 如果展开运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象
对象中对象属性的展开
- 对象中还有对象 不会展开对象中的对象属性
对象展开运算符的应用
复制对象
const a = {x:1,y:2};
const b = {a:1};
const c = {...a,...b}
用户参数和默认参数
// 对象解构 函数参数加默认值
const logUser = ({username = 'ZhangSan',age = 0,sex = 'male'} = {}) => {
console.log(username,age,sex)
}
//使用展开运算符
const logUser = userParam => {
cons defaultParam = {
username:'ZhangSan',
age = 0,
sex = 'male'
};
const param = {...defaultParam,...userParam};
}
Set集合
Set是什么
- 数组是一系列有序的数据集合
- Set是一系列无序、没有重复值的数据集合
const s = new Set();
s.add(1);
s
s.add(1);
// s.length 2
//s {1,2}
- Set没有下标取标识每一个值,所以Set是无序的,也不能像数组那样通过下标取访问Set的成员
Set实例的方法和属性
add方法
const s = new Set();
s.add(1).add(2).add(1);
delete方法
s.delete(1);
clear方法
s.clear();//清楚set集合所有内容
forEach方法
s.forEach(function(value,key,set){
//Set 中的 value = key
console.log(value,key,set)
console.log(this) //指向 document
},document)
//按照成员添加进集合的顺序遍历
size属性
s.size
Set构造函数的参数
-
数组
const s = new Set([1,2,1]); // s {1,2}
-
字符串、arguments、NodeLIst、Set等
const s = new Set('hi'); //s {'h','i'} function func(){ console.log(new Set(arguments)); } func(1,2,1) console.log(new Set(document.querySelectorAll('p'))); console.log(new Set(s));
判断重复的方式
const s = new Set([1,2,1]);
//set 对重复值的判断基本遵循严格相等(===)
//但是对于NaN的判断与 === 不同,Set中NaN等于NaN
const s = new Set([NaN,2,1,NaN]);
什么时候使用Set
数组或字符串去重时
不需要通过下标访问,只需要遍历时
为了使用Set提供的方法和属性时(add delete clear has forEach size等)
Set的应用
数组去重
const s = new Set([1,2,1])
console.log([...s])
console.log([...new Set([1,2,1])])
字符串去重
const s = new Set('adsabd');
console.log([...new Set('adsabd')].join('0'))
存放DOM元素
const s = new Set(document.querySelectorAll('p'))
console.log(s)
s.forEach(function(elem){
elem.style.color = 'red';
});
Map集合
Map是什么
-
Map和对象都是键值对的集合
-
键->值 key->value
-
Map和对象的区别
-
对象一般用字符串当做键
-
const obj = { name:'alex',true:'true'}
-
基本数据类型: 数字、字符串、布尔值、undefined、null
-
应用类型:引用对象([]、{}、函数、Set、Map等)
-
都可以作为Map的键
Map实列的属性和方法
set方法
const m = new Map();
m.set('age',18).set(true,'true').set('age',20);
console.log(m)
get方法
const m = new Map();
m.set('age',18).set(true,'true').set('age',20);
console.log(m.get('age'))
//不存在的 会返回undefined
has方法
m.has('age')
delete方法
m.delete('age')
//删除不存在的成员 什么都不会发生 也不会报错
clear方法
m.clear()
forEach方法
m.forEach(function(value,key,map){
console.log(this);//document
},document)
size属性
//对象没有size属性
m.size
Map构造函数的参数
数组
//只能传二维数组,必须体现出键和值
console.log(new Map(['name','alex'],['age',18]))
Set、Map
//set 中也必须体现出键和值
const s = new Set(['name','alex'],['age',18])
console.log(new Map(s))
const m1 = new Map(['name','alex'],['age',18]);
console.log(new Map(m1))
Map的注意事项
判断键名是否相同的方式
- 基本遵循严格相等(===)
- 列外就是NaN ,在Map中是相等的
什么时候使用Map
- 如果只需要 k – v的结构,或者需要字符串以外的值做键,使用Map更适合
Map的应用
const [p1,p2,p3] = document.querySe;ectoryAll('p')
const n = new Map([p1,'red'],[p2,'green'],[p2,'blue']);
m.forEach(function(color,elem) => {
elem.style.color = color;
})
Iterator
作用
- 遍历器(迭代器)
寻找Iterator
let a = [1,2][Symbol.iterator]() //a Array Iterator {}
a.next() //{value: 1, done: false}
a.next() //{value: 2, done: false}
a.next() //{value: undefined, done: true}
为什么需要iterator
- iterator 是统一的一个遍历方式
更方便使用iterator
- 我们一般不会直接使用iterator 去遍历
- 比如 es6 提供的 for of
for … of的用法
认识 for…of
const arr = [1,2,3]
/*
for of 的本质就是封装了这一套东西
const it = arr[Symbol.iterator]();
let next = it.next();
while(!next){
console.log(next.value);
next = it.next;
}
*/
for(const item of arr){
console.log(item);
}
- for of 循环只会遍历出那些done为false时,对应的值
与beak、continue一起使用
const arr = [1,2,3]
for(const item of arr){
if(item == 2){
break;
}
console.log(item);
}
在for of中取到数组的索引
const arr = [1,2,3]
//keys()得到的就是索引的可遍历对象,可以遍历的索引值
for(const key of arr.keys){
console.log(key);
}
//valus()得到的是值
for(const v of arr.values){
console.log(v);
}
//entries() 得到是索引 + 值得数组得可遍历对象
for(const entrues of arr.entrues()){
console.log(entrues);
}
//使用解构赋值 直接拿到索引 + 值
for(const {index,value} of arr.entrues()){
console.log(index , value);
}
原生可遍历与非原生可遍历
什么是可遍历
- 只要有Symbol.iterator方法,并且这个方法可以生成可遍历对象,就是可遍历的
- 只要可遍历,就可以使用 for…of循环来统一遍历
原生可遍历有哪些
- 数组
- 字符串
- Set
- Map
- arguments
- NodeList
非原生可遍历有哪些
- 一般对象 可以使用 for in 自己添加Symbol.iterator方法
const person = {sex:'male',age:18};
person[Symbol.iterator] = () => {
let index = 0;
return {
next() {
index++;
if (index === 1) {
return {
value: person.age,
done: false
};
} else if (index === 2) {
return {
value: person.sex,
done: false
};
} else {
return {
done: true
};
}
}
};
};
使用了Iterator
- 原生可遍历
- Array数组
- String数组
- Set
- Map
- 函数得arguments对象
- NodeList对象
-
- 数组得展开运算符
- 数组得解构赋值
ES6中新增加方法
includs()方法
- 判断字符串中是否包含有某些字符
//基本用法
console.log('abc'.includes('a')); // true
console.log('abc'.includes('ab')); // true
console.log('abc'.includes('bc')); // true
console.log('abc'.includes('ac')); // false
// 第二个参数
// 表示开始搜索的位置,默认是0
console.log('abc'.includes('a')); //ture
console.log('abc'.includes('a',0)); //true
console.log('abc'.includes('a',1)); //false
- 实际开发中的应用
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/144817.html