ES6(尚硅谷)
[1.let声明变量]
- 变量不能重复声明
- 块级作用域有效,只在代码块中起作用
- 不存在变量提升(要先声明再使用)
- 不影响作用域链
//1.变量不能重复声明
let star='z';
let star='x';//报错
[2.const声明常量]
- 一定要有初始值
- 一般常量使用大写
- 常量的值不能修改
- 块级作用域
- 对于数组和对象的元素修改,不算做对常量的修改,不会报错(指向的地址没有发生改变)
const TEAM=['A','B'];
TEAM.push('C');//给数组添加一个元素C
[3.变量的解构赋值]
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,被称为解构赋值
- 数组的解构
将数组的单元值快速批量赋值给一系列变量的简洁语法
const F4 = ['小沈阳','刘能','赵四','宋小宝']
let [xiao,liu,zhao,song] = F4; //中括号
console.log(xiao)
console.log(liu)
console.log(zhao)
console.log(song)
- 对象的解构
将对象属性和方法快速批量赋值给一系列变量的简洁语法
const zhao = {
name : '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品")
}
}
let {name,age,xiaopin} = zhao;//花括号
console.log(name);
console.log(age);
console.log(xiaopin);
[4.模板字符串]
- 声明
let str = `我也是一个字符串`
console.log(str,typeof str);
- 特点
- 内容中可以直接出现换行符
let str = `<ul>
<li>RHF</li>
<li>RHF</li>
</ul>`;
- 变量拼接
${lovest}
let lovest = 'RHF';
let out = `${lovest}是最帅的`;
console.log(out) //RHF是最帅的
[5.对象的简化写法]
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
let name = 'aaa';
let change = function(){
console.log('aaa');
}
const school = {
name,
change,
improve(){
consolg.log('bbb');
}
}
[6.箭头函数]
属于表达式函数,不存在变量提升
- this是静态的,this始终指向函数声明时所在作用域下的this的值(箭头函数不会创建自己的this,只会从自己的作用域链的上一层沿用this)
function A(){
console.log(this.name)
}
let B = () => {
console.log(this.name);
}
window.name = '尚硅谷';
const school = {
name: 'ATGUIGU'
}
//直接调用
A() //尚硅谷
B() //尚硅谷
//call
A.call(school); //ATGUIGU****
B.cal(school); //尚硅谷****
- 不能作为构造实例化对象(对象的方法——>外层作用域的this)
let A(name,age) => {
this.name=name;
this.age=age;
}
let me = new A('xiao',123);
console.me //error
- 不能使用arguments变量(可使用剩余参数)
let fn = () => {
console.log(arguments);
}
fn(1,2,3) //error
- 箭头函数可以直接返回一个对象(加括号的函数体返回对象字面量的表达式)
const fn = (unname)=>
({
name:unname;//对象花括号易混函数体花括号,要加个小括号
})
- 简写
- 省略小括号,当形参有且只有一个的时候
- 省略花括号,当代码体只有一条语句的时候,此时return也必须省略
- 箭头函数适合与this无关的回调(定时器,数组方法的回调)
- 箭头函数不适合与this有关的回调(DOM事件回调[事件回调函数使用箭头函数时,this为全局的window],对象的方法)
[7.函数默认参数值]
- ES6允许给函数参数赋初始值
- 传了新的参数就用传的参数,没有传参就用默认值
- 可以给形参赋初始值,一般位置要靠后
- 与解构赋值结合
function A({host='127.0.0.1',username,password,port}){
console.log(host+username+password+port)
}
A({
username:'ran',
password:'123456',
port:3306
})
[8.rest参数]
用于获取函数的实参,用来代替arguments
- rest参数必须放到参数(函数使用的形参)最后
[9.扩展运算符...]
能将数组转换为逗号分隔的参数序列
- 数组的合并
const A = ['aa','bb'];
const B = ['cc','dd'];
const C = [...A,...B];
console.log(C) //[aa,bb,cc,dd]
- 数组的克隆
const A = ['a','b','c'];
const B = [...A];
console.log(B) //[a,b,c]
- 将伪数组转化为真正的数组
const A = documents.querySelectorAll('div');
const B = [...A];
console.log(B) // [div,div,div]
[10.Symbol]
ES6引入了一种新的原始数据类型Symbol,表示
独一无二的值。它是Javascript语言的第七种数据类型,是一种类似于字符串的数据类型。
特点
- Symbol的值是唯一的,用于解决命名冲突的问题
- Symbol不能与其他的数据类型进行运算
- Symbol定义的对象属性不能使用for...in...循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
- 创建
let s = Symbol('aa');
let s2= Symbol('aa');
console.log(s===s2) //false
let s3 = Symbol.for('bb');
let s4 = Symbol.for('bb');
comsole.log(s3===s4) ///true
- Symbol的内置值
class Person {
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测了");
return false;
}
}
let o = {};
console.log(o instanceof Person); //我被用来检测了,false
应用
- 给对象添加方法(1)
let game = {
name : 'ran'
}
let methods = {
up:Symbol()
down:Symbol()
}
game[methods.up]=function(){
console.log('aaa');
}
game[methods.down]=function(){
console.log('bbb');
}
console.log(game) // name: 'ran',Symbol(),Symbol()
- 给对象添加方法(2)
//不用查找对象原来有无此方法名
let youxi = {
name: '狼人杀',
[Symbol('say')]:function(){
console.log('阿萨德')
}
}
console.log(youxi) // name:'狼人杀',Symbol(say)
[11.迭代器]
- 迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。
- 任何数据结构只要部署lterator接口,就可以使用
for...of...完成遍历操作。
具备iterator接口的数据类型
- Array
- Argunments
- Set
- Map
- String
- TypedArray
- NodeList
这个接口就是对象里面的一个属性,属性的名字叫Symbol.iterator,也可以自己对结构进行布置iterator接口。
工作原理
- 先创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用
next()方法,指针自动指向数据结构的第一个成员 - 接下来不断调用
next()方法,指针一直往后移动,直到指向最后一个成员 - 每次调用
next()方法就会返回一个包含value和done属性(是否完成)的对象
迭代器可以自定义遍历数据
for...in...与for...of...
for(let i in data){
i是键名
}
for(let i of data){
i是键值
}
数组常用的遍历方法
forEach:找到目标还会继续循环,并且不受return和break的影响some:找到目标后,可以通过return结束循环
const arr=[]
arr.some((item,index)=>{
if(item=='zzl'){
console.log(item)
return true
}
})
every:只要每一项都满足every里面的判断条件,则最终返回ture
const arr=[
{id:1,state:true},
{id:2,state:true}
]
//判断数组中的所有state是否都为true
const result=arr.every(item=>item.state)
filter:把满足条件的数据重新过滤到新数组中
const data=arr.filter(item=>item.state)
reduce:第一次循环累加的结果默认等于初始值,以后循环累加的结果等于上一次累加的结果加上循环项里的数据。
arr.filter(item=>item.state).reduce(累加的结果,当前循环项)=>{ },初始值)
const arr=[{id:1,state:true,price:10}]
let sum=0
arr.filter(item=> item.state).reduce((sum,item)=>{
return sum+= item.price
//return给下一次累加使用
},0)
[12.生成器]
生成器是一个特殊的函数,是异步编程新的解决方案。
- 函数名和
function中间有一个* yield是函数代码的分隔符- 需要用
next()方法调用,依次执行以yield分割的一段,并且返回yield后面的值 next()中传入的值将作为yield的返回结果
function * fun(){
console.log('111');
yield '返回值'
console.log('222');
}
let a=fun();
//输出
//console.log(a);//输出一个迭代器对象(有next方法)
console.log(a.next());//输出111{value:'返回值',done:'false'}
console.log(a.next());//输出222{value:'undefined',done:'ture'}
//遍历
for(let v of fun()){
console.log(v);
}
//111
//返回值
//222
生成器函数的参数传递
function * fun(arg){
console.log(arg);//输出aaa
let one=yield 111;
console.log(one);//输出bbb
let two=yield 222;
console.log(two);//输出ccc
let three=yield 333;
console.log(three);//输出ddd
}
let a=fun('aaa');
console.log(a.next());//第一次调用next
//next方法可以传入实参
//第二次调用next的实参将作为第一个yield的整体返回结果
console.log(a.next('bbb'))//输出{value: 222, done: false}
console.log(a.next('ccc'))
console.log(a.next('ddd'))
用生成器函数的方式解决回调地狱的问题
function one(){
setTimeout(()=>{
console.log('111')
iterator.next()
},1000)
}
function two(){
setTimeout(()=>{
console.log('222')
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log('333')
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
模拟异步获取数据
function one(){
setTimeout(()=>{
let data='用户数据';
iterator.next(data)//调用并传参
},1000)
}
function two(){
setTimeout(()=>{
let data='订单数据';
iterator.next(data)
},2000)
}
function three(){
setTimeout(()=>{
let data='商品数据';
iterator.next(data)
},3000)
}
function * gen(){
let users=yield one();
console.log(users)
let orders=yield two();
console.log(orders)
let goods=yield three();
console.log(goods)
}
let iterator = gen();
iterator.next();
[13.Promise]
异步编程新的解决方法,语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或者失败的结果。
function fun(){
return new Promise((resolve,reject)=>{
//如果成功就调用resolve
let data='数据库中的数据';
resolve(data); //promise状态变为成功
//如果失败就调用reject
let err='数据库读取失败';
reject(err);//promise状态变为失败
})
}
var promise = fun()
promise.then(//调用then方法
function(success){//promise状态变为成功后then会调用第一个回调函数
console.log(success);
},function(err){//promise状态变为失败后then会调用第二个回调函数
console.log(err);
}
)
Promise.then()方法
- then()函数返回的实际也是一个Promise对象
- 当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined
- 当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值
- 当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected
Promise.catch()方法
- catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数
- 相当于一个语法糖,直接在出错的时候使用
reason,只有Promise.then也能实现
<script>
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
reject('出错啦')
},1000)
})
p.catch(reason => {
console.log(reason)
})
</script>
[14.集合]
Set
ES6提供了新的数据结构
set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for…of…进行遍历,集合的属性和方法:
- size返回集合的元素个数
- add增加一个新元素,返回当前集合
- delete删除元素,返回boolean值
- has检测集合中是否包含某个元素,返回boolean值
<script>
let s = new Set();
let s2 = new Set(['A','B','C','D'])
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('E');
//删除元素
s2.delete('A')
//检测
console.log(s2.has('C'));
//清空
s2.clear()
console.log(s2);
</script>
应用
let arr=[1,2,3,4,3,2,1];
//数组去重
let result=[...new Set(arr)];//[1,2,3,4]
//交集
let arr2=[1,4,5,6,5,6];
let result2=[...new Set(arr)].filter(item=>{
let s2=new Set(arr2);//[1,4,5,6]
if(s2.has(item)){
return true;
}else{
return false;
}
})
console.log(result2);//[1,4];
//并集
let arr3=[...new Set([...arr,...arr2])]
console.log(arr3);//[1,2,3,4,5,6]
//差集,交集的逆运算
let arr2=[1,4,5,6,5,6];
let result2=[...new Set(arr)].filter(item=>{
let s2=new Set(arr2);//[1,4,5,6]
if(!s2.has(item)){//item不在s2里面
return true;
}else{
return false;
}
})
console.log(result2);//[1,4]
Map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和「for…of…』进行遍历。
- size:返回Map元素的个数
- set:增加一个新元素,返回当前Map
- get:返回键名对象的键值
- has:检测Map中是否包含某个元素,返回Boolean值
- clear:清空集合,返回undefined
[15.Class]
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- js高级笔记里面更详细,待补充
[16.数值扩展]
- Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-16
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}else {
return false;
}
}
console.log(equal(0.1 + 0.2 === 0.3)) //false
console.log(equal(0.1+0.2,0.3)) //true
- 二进制和八进制
let b = 0b1010; //2进制
let o = 0o777; //8进制
let d = 100; //10进制
let x = 0xff; //16进制
console.log(x) //255(输出的都是十进制)
//检测一个数是否为有限数
console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity)); //false
//检测一个数值是否为NaN
console.log(Number.isNaN(123)) //false
//字符串转整数
console.log(Number.parseInt('5213123love')); //5213123
console.log(Number.parseFloat('5.123123神器')); //5.123123
//判断是否为整数
console.log(Number.isInteger(5)); //true
console.log(Number.isInteger(2.5)); //false
//将小数部分抹除
console.log(Math.trunc(3.45345345345)) //3
//检测一个数到底是正数、负数、还是0
console.log(Math.sign(100)) //1
console.log(Math.sign(0)) //0
console.log(Math.sign(-123)) //-1
[17.对象方法扩展]
<script>
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120)) //true
console.log(Object.is(NaN,NaN)) //false
//2.Object.assign 对象的合并
//如果两个对象有重复的属性或方法,后面的会将前面的内容覆盖
const a = {
name:'ran',
age:12
}
const b = {
pass:'i love you'
}
console.log(Object.assign(a,b))
//{name:'ran',age:'12',pass:'i love you'}
//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name:'尚硅谷'
}
const cities = {
xiaoqu:['北京','上海']
}
Object.setPrototypeOf(school,cities)
console.log(Object.getPrototypeOf(school))
//{xiaoqu: Array(2)}
console.log(school) //{name: "尚硅谷"}
</script>
[18.模块化]
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块功能主要有两个命令构成:export和inport
- export命令用于规定模块的对外接口
- inport命令用于输入其他模块提供的功能
暴露export
- 统一暴露
let school = '尚硅谷';
function findjob(){
console.log('找工作吧');
}
export {school,findjob}
- 默认暴露
export default {
school:'ATGUIGU',
change:function(){
console.log('我们可以改变你')
}
}
引入语法import
- 通用导入方式
import * as m1 from "./src/js/m1.js"
import * as m2 from "./src/js/m2.js"
import * as m3 from "./src/js/m3.js"
- 解构赋值
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"
- 简便形式(只针对默认暴露)
import m3 from "./src/js/m3.js"