欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

ES6 概念与语法 (I)

最编程 2024-04-28 18:19:24
...

什么是ES6

ES的全称是ECMScript,它是由ECMA国际标准化组织制定的一项弱语言脚本的标准化规范

为什么要使用ES6

每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身有一些令人不满意的地方。

  • 变量的提升,给程序带来了很大的不可预测性。
  • 语法过于松散,实现相同的功能,不同的人可能会写出不的程序。

ES6新增语法

let 关键字(★★★)

ES6中新增的关键字,用于声明变量 ,不具有变量提升。

  • let声明的变量只在所处的块级有效,俗称块级作用域

    if(true){
      let a=10;
    }
    console.log(a)   // a is not defined
    

注意: 在大括号中使用let声明变量会具块级作用域 ,对象的大括号不具备块级作用域,let声明的变量不具有变量提升,var声明的变量具有变量提升,但不具备块级作用域。

console.log(a); //a is not defined
let a=10;       //let声明的变量不具备变量提升

let-for 不泄露

避免for循环变量泄露到全局作用域上

// 1.避免全局污染问题
var i=100;
for(var i=0,i<10,i++){
}
console.log(i); // i=10 
//问题是:变量泄露到了全局上

//2.解决:Es6引入了let来解决
var j=90forlet j=0,j<10,j++){
}
console.log(j) // j=90

const 关键字(★★★)

作用与 var、let相同,也是用于定义变量 建议 const声明的变量必须大写

const声明常量,常量就是值(内存地址)不能更改的量

  • const 具有块级作用域
  • const 不具有变量提升
  • const 声明常量时必须赋值
  • const 声明的变量,如是基本数据类型则值 不可改变,如是复杂数据类型则地址不可改变

总结

关键字 初始值 块级作用域 变量提升 重新赋值 通过window调用
let - x Yes No
const YES x No No
var - x Yes Yes
let const var
不具有变量提升 不具有变量提升 具有变量提升
配合大括号{} 一起使用具有块级作用域 配合大括号{}一起使用具有作用域 全局变量不具有块级作用域
值 可以更改 值不可以更改 值 可以更改
声明时可不赋值 声明时必须同时赋值 声明时可不赋值
不挂载到window上 不挂载到window上 可挂载到window上

Es6的模块化规范

注意 下面两条是 node.js中的导入与导出

导入其它模块使用 require()方法

模块对外共享成员使用module.exports对象

  • 导入其它模块成员使用 import 关键字
  • 向外共享模块成员使用 export 关键字

默认导入与默认导出

  • 默认导入时的接收名称可以是任意名称 不能是数字开头
  • 默认导出 每个模块中只允许使用唯一的一次 export default{ }
//默认导入 
import xxx from "文件地址"
 let a=1;
 function show (){}
​
//默认导出 只需要挂载要导出的成员show
export default{
    show
}

按需导入与按需导出

  • 按需导入的名称需要以按需导出的名称对应

  • 在按需导入时 可以使用 as关键字进行重命名

  • 按需要导出 在每个模块中可以多次使用

  • 按需导入可以和默认导入一起使用

    //按需导入 { }中的为导入成员
    import { a,b } from
    
    //按需导出 逐个导出
    export let a="a"
    export let b="b"
    
  • 直接导入并执行代码

    • 如果只是想要单纯的执行某个模块中的代码,并不需要得到模块中的向外共享的成员。此时可以直接导入并执行里面的代码

      for(let i=0;,i<3;i++){
      console.log(1)
      }
      //直接导入,并执行代码
      import "./05_m3.js"
      

node.js中如何实现模块化

  • 导入其它模块使用 require()方法
  • 模块对外共享成员使用module.exports对象

解构赋值

从数组或对象的提取出值,重新按照对应的位置,赋值给新变量,解构赋值的目的是方便取值

数组解构

 let [a, b, c] = [1, 2, 3];
 console.log(a)//1
 console.log(b)//2
 console.log(c)//3
//如果解构不成功,变量的值为undefined

在es6允许从数组中取值,按照对应位置,对变量赋值,对象同理

对象的解构

 let person = { name: 'zhangsan', age: 20 }; 
 let {name,age}=person;
 console.log(name) // `zhangsan`
 console.log(age)  // 20
 
 let {name:myName,age:myAge}=person; //myName myAge 属于别名
 console.log(myName) //'zhangsan'
 console.log(myAge)  //20

交换数组元素中的值

let x=20;
let y=30;
[x,y]=[y,x];
console.log(x,y)

注意 模式匹配,不写var就是重新赋值,而不是重新声明+赋值。

小结

  • 数组解构赋值就是把数组里面的值分解出来,然后重新按照位置赋值给变量。对象解构赋值也是同理。
  • 如果解构不成功,变量个数跟赋值的个数不匹配的时候,变量的值是undefined
  • 数组解构用中括号包裹,对象解构用大括号包裹 ,多个变量用逗号隔开。
  • 利用解构赋值能够让我们方便的取对象中的属性和方法。

箭头函数

作用:定义匿名函数,简化回调函数和普通函数的写法

() => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体
const fn = () => {}//代表把一个函数赋值给fn

简化

  • 参数只有1个,可以省略小括号

  • 方法体只有一行代码,可以省略大括号,省略大括号后,默认返回此表达式结果。

    //优势1;如果形参只有一个,可以省略括号
    var fn=x=>{
      return x*2;
    }
    //优势2:如果函数体只有一行代码,可以省略大括号,默认返回这个表达式的结果
    var fn=x=>x*2;
    concole.log(fn4(10));
    

this.

箭头函数不绑定this.箭头函数没有this关键字,要是在箭头函数中使用this ,this指向的是箭头函数定义位置的外层函数的作用域的this

  • function函数:this指向的是函数的调用者

  • 箭头函数:this指向的是外层作用域链上的this

    const obj={name:'张三'}
    function fn(){
     console.log(this); //this 指向的是obj对象
      return()=>{
       //this指向的是箭头函数定义的位置,外层的fn函数,fn函数指向的是obj对象,所以这个this也指向是obj对象
       console.log(this); 
      }
    }
    const resFn=fn.call(obj); //call将fn函数this的指向obj
    resFn();
    
  • 由于箭头函数没有自己的this,因此,不能使用 call()、apply()、bind()等方法来改变this的指向

     let adder = {
         base:1,
         add:function(a){
           let f=v=>v+this.base
           let b={
             base:2
           }
           return f.call(b,a);
         }
     }
     consolelog(adder.add(1)) // 2
    

箭头函数的特点

  • 不能用作构造函数, 和new
    • 箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候查看
  • 不能使用arguments
// 1. 箭头函数不能被用作构造函数使用, 不能用new来调用
// 原因箭头函数里没有自己的this指向, 所以也改不了
 var Person = (theName, theAge) => {
    this.name = theName;
    this.age = theAge;
 }
 var p = new Person();
 console.log(p);

// 2. 箭头函数不能使用arguments
 var fn = () => {
     console.log(arguments);
 }
 fn(10, 20, 56);

函数形参默认值

funciton/箭头函数中允许在形参中赋予默认值,当不传入参数的时候/形参的值是undefinde,会被默认值覆盖掉。

// 使用默认值解决问题
function fnOne(a = 0, b = 0) {
    console.log(a + b);
}
fnOne();
fnOne(10, 20);

// 箭头函数体也能使用默认值
let fnTwo = (a = 0, b = 0) => {
    console.log(a + b);
}
fnTwo();
fnTwo(100, 200);

箭头函数的特点

  • 不能用作构造函数和new

    • 箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候查看。
  • 不能使用arguments

    // 1. 箭头函数不能被用作构造函数使用, 不能用new来调用
    // 原因箭头函数里没有自己的this指向, 所以也改不了
    // var Person = (theName, theAge) => {
    //     this.name = theName;
    //     this.age = theAge;
    // }
    // var p = new Person();
    // console.log(p);
    
    // 2. 箭头函数不能使用arguments
    // var fn = () => {
    //     console.log(arguments);
    // }
    // fn(10, 20, 56);
    

小结

  • 箭头函数中不绑定this,箭头函数中没有this关键字,如在箭头函数中使用this,this指向所定义位置的外层作用域的this指向谁,它就指向谁。
  • 箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题

剩余参数

剩余参数是将一个不定数量的参数表示为一个数组,例如:实参数量大于形参数量时,使用.....剩余参数可以将实参多余的保存在数组中,参数值,形成一个数组使用。

  • 一般配合箭头函数,因为箭头函数内不能用arguments

  • 必须出现在形参的最后面

    //剩余参数的使用
    function sum (first, ...args) {
         console.log(first); // 10
         console.log(args); // [20, 30] 
     }
     sum(10, 20, 30)
    
    
    //剩余参数和解构配合使用
    let students = ['wangwu', 'zhangsan', 'lisi'];
    let [s1, ...s2] = students; 
    console.log(s1);  // 'wangwu' 
    console.log(s2);  // ['zhangsan', 'lisi']
    
    

扩展运算符

扩展运算符是将数组或对象扩展成以逗号分隔的参数数据序列,可以应用在合并两个数组与将伪数组转换成真数组,从而使用数组的方法 (与扩展运算符相反)

扩展运算符应用于合并数组

// 方法一 
 let ary1 = [1, 2, 3];
 let ary2 = [3, 4, 5];
 let ary3 = [...ary1, ...ary2];
 // 方法二 
 ary1.push(...ary2);
 

扩展运算符应用于对象

// 对象的展开使用
var obj = {
    age: 18,
    sex: "不知道",
    address: "泰国"
}
console.log({...obj}); // 不需要forin来拷贝对象了

// 既然是拷贝内容, 那是深还是浅拷贝呢?
// ...只是第一层内容的拷贝(所以是浅拷贝)
var obj2 = {
    age: 18,
    grade: [90, 100, 98],
    family: {
        fName: "李"
    }
}

var newObj = {...obj2}; // ...常用于内容的复制(浅拷贝)
console.log(newObj);
newObj.grade[0] = 1000;
console.log(obj2); // 发现里面的grade第一个值为1000, 被影响了, 证明...内容拷贝是浅拷贝

// 如果只有一层, 直接用...复制内容过来就ok
// 但是如果有多层, 调用deepCopy方法即可深拷贝

扩展运算符用于将伪数组转换成真数组

//将伪数组转换成真数组,这样就可以使用数组的方法了
//例如使用数组的方法push 向数组的末尾添加数据
let oDivs = document.getElementsByTagName('div'); 
oDivs = [...oDivs];
oDivs.push("1")

Es6新增数组方法

Array.from()

  • 将伪数组或可遍历的对象转换成真正的数组。(例如使用真数组的push方法在末尾添加值 )

  • Array.from可接受第二参数,第二个参数可以对每个元素进行处理,将处理后的值返回给原数组。(作用类似于数组的map方法)

     let arrayLike = { 
         "0": 1,
         "1": 2,
         "length": 2
     }
     let newAry = Array.from(arrayLike, item => item *2)//[2,4]
    
    

    注意:如果是对象,那么属性需要写对应的索引

Array.find()

  • 用于遍历数组找出一个符合条件的数组成员,如果没找到返回undefined

    let ary = [{
         id: 1,
         name: '张三'
     }, { 
         id: 2,
         name: '李四'
     }]; 
     let target = ary.find((item, index) => item.id == 2);//找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
    
    

Array.findIndex()

用于遍历数组找出符合条件的数组成员的索引,如果没找到则返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9); 
console.log(index); // 2

Array.includes()

判断某个数组是否包含给定值,返回布尔值。

[1, 2, 3].includes(2) // true 
[1, 2, 3].includes(4) // false

Array.forEach()

  • 单纯的遍历数组,无返回值
//forEach只是单纯的引用数组,没有返回傎
var arr=[1,2,3,4,5,6,7]
arr.forEach((value,index)=>{
 console.log(index+"--"+value)
})

Array.map()

  • 遍历数组 ,收集每次return的结果,返回全新数组。(类似 数组from的方法)
//  map() - 遍历 - 收集每次return结果 - 返回全新数组
var arr = [1, 5, 7, 3, 10, 2, 4];
var result2Arr = arr.map(function(value, index){
    return value + 1;
})
console.log(result2Arr);

Array.filter()

  • filter() --遍历数组 并过滤--收集每次return结果,返回一个全新的数组
//filter()-遍历数组并过滤,收集每次return结果,返回一个全新的数组
var arr = [1, 5, 7, 3, 10, 2, 4];
var result3Arr=arr.filter((value,index)=>{
  return value>=5;
})
console.log(result3Arr)

Array.every()

  • every()---遍历数组,--查找不符合条件的--直接返回false----不继续遍历数组 (与数组的方法some相反)
//every()--遍历数组--查找不符合条件的---直接返回false---不继续遍历数组
var arr5=[20, 21, 1, 18, 19, 23];
var result5=arr5.every((value,index)=>{
 return value>18;
})
console.log(result5)

Array.some()

  • some() --找到符合条件的---直接返回true---不继续循环 (与数组every()的方法相反)
// some() - 找到符合条件的 - 直接返回true - 不继续循环
var result6 = arr5.some(function(value, index){
    return value < 18;
})
console.log(result6);

小结

数组调用的方法 作用 返回值
array.from((伪数组,item)=>{item*2}) 将伪数组转换成真数组,从而使用数组的方法,参数二是,遍历的每一项从而在每一项进行处理,将处理后的值返回给数组 (与map()方法相同) 数组
array.find((item,index)=>item.id==2) 遍历数组---找出符合条件的数组成员,没找到则返回undefined ---只会匹配一个 返回数组成员
array.findIndex((value,index)=>value>9) 遍历数组---找出符合条件的数组成员的位置,如果没找到则返回 -1, ----只会匹配一个 返回 数组 的索引
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
判断数组中是否存在这个值 返回的是布尔值
array.forEach( (value,index)=>{console.log(index+“--”+value)} ) 只是单纯的遍历数组 无返回值
array.map( (value,index)=>{ return value+1 ; } ) 用于遍历数组,收集每次return的结果--返回全新的数组 (与from() 作用相同) 返回新数组
array.filter ( (value,index)=>{ return 条件}) 过滤---用于遍历数组,查找符合条件的数组成员,收集 return的结果,返回全新的数组 返回新数组
array.every ((value,index) { return value value 条件} ) 遍历数组--找到不符合条件的--直接返回false--不继续循环。(与some相反) 返回布尔值
array.some( (value,index) ) 遍历数组--找到符合条件的--直接返回true---不继续循环 (与every相反) 返回布尔值

案例--全选和反选

// 需求: 点击小多选框, 都勾选时, 全选框也勾选
// 思路: 声明个变量, 遍历每个小多选框, 如有一个未选中, 则变量直接保存false, 赋予给全选框, 否则全选框设置为true

// 1. 获取标签
var checkAll = document.getElementById("checkAll");
var ckList = document.querySelectorAll(".ck"); // 所有小多选框

// 2. 全选影响所有小的
checkAll.onclick = function(){
    var allChecked = this.checked;
    Array.from(ckList).map(function(el){//使用from转换成真数组,在使用map对每个选项进行赋值
        el.checked = allChecked;
    })
}

// 3. 小影响多
var ckArr = Array.from(ckList); //使用from将伪数组转成真数组 
ckArr.map(function(el){         
    el.onclick = function(){
        var isAll = ckArr.every(function(el){return el.checked == true}); // 筛选是否有不符合条件的返回false
        checkAll.checked = isAll == false ? false : true;
    }
})

字符串String的扩展方法

模板字符串

  • Es6新增的创建字符串的方式,使用反引号定义

     let result = { 
         name: 'zhangsan', 
         age: 20,
         sex: '男' 
     } 
     // ${} 用来解析变量
     let html = ` <div>
         <span>${result.name}</span>
         <span>${result.age}</span>
         <span>${result.sex}</span>
     </div> `;
    

startsWith() 和 endsWith()

  • startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
  • endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello world!';
str.startsWith('Hello') // true 
str.endsWith('!')       // true

repeat()

  • repeat方法表示将原字符串重复n次,返回一个新字符串
'x'.repeat(3)      // "xxx" 
'hello'.repeat(2)  // "hellohello"

小结

startsWith endsWith repeat
string.startsWith() string.endsWith() string.repeat()
表示字符串是否在原字符串的头部,返回布尔值 表示 字符串是否在原字符串的尾部,返回布尔值 表示将原字符串重复n次, 重新返回一个新字符串.

Es6新增 数据类型

Set容器

  • 无序不重复的value集合体
let set = new Set([1, 3, 3, '9', true, 2, 3, 4, 1, 5, true, '9']);
  • set()
  • set().add(value) 向set数组结构中添加value值
  • set().delete(value) 向set数组结构中删除value值
  • set().has(value) 向 ste数组结构中查找value值 ,如果存在则返回true,
  • set.size()容器的长度
  • set.clear()清空
  1. 应用场景:去除数组中重复的元素
  2. 区别:数组是无序可重复的,而set()是无序不重复的value集合体
  3. 备注:可以使用Array.from()将伪数组转换成真数组
add(value) delete(value) has(value) clear(value)
Set.add(value) Set.delete(value) Set.has(value) Set.clear(value)
向Set结构中添加值 删除Set结构中的value值 ,返回一个布尔值 ,表示 删除是否成功 表示value是否为 Set结构里的值,返回布尔值 清除Set结构中的数据, 没有返回值

Map容器

无序不重复的key--value的集合体

let map = new Map([['bbcc', 12],[25, 'age']]);
  • Map()
  • Map().set(key,value) // 添加
  • map.get(key) //读取
  • map.delete(key) //删除
  • map.has(key)//查询
  • map.size() //容器的长度
  • map.clear() //清空

区别:object对象的key只能是字符串,而Map的key 可以是任意类型

键值对的简化写化

  • key与value变量名,同名可以只写key

  • 当value是:function ,可以省略 :function

    let x = 10;
    let y = 20;
    let obj = {
        x,
        y, 
     // 相当于 y: y // 前面的y是key的名字, 后面y是变量名, 会使用20
        uname: 'uname',
     // 这个value不是 变量名, 所以不能省略
        getPosition(){ 
     // 省略了:function 相当于 getPosition: function(){return obj.x}
            return obj.x
        }
    }
    

面试题

  1. 数组中的forEach和map的区别

    • forEach和map都可以遍历数组,都有三个参数,函数里的this都指向window, forEach只是单纯遍历数组没有返回值 ,map是收集return的结果,返回全新的数组
  2. 说说 ES5和ES6的区别

    • ES6新增了 let 、const 关键字,let和const不具备var的变量提升

      • let和const 在大括号 { }里面使用会形成 块级作用域
      • const 声明的同时必须赋予初始值
    • 模板字符串,ES6新增了 创建字符串的方式,使用${} 即可解析变量。

    • 箭头函数 从语法上 比普通的函数要简单

      • 特点:箭头函数的this指向的是箭头函数外层函数作用域的this的指向
    • 扩展运算符,可以将伪数组转换成真数组或将两个数组合并

    • 剩余参数,将实参数量大于形参数量的多余数据以数组的形式保存起来

    • 解构赋值,将数组或对象进行分解,并按照对应的位置的变量进行赋值

    • set数组结构 : set容器是一个不重复无序的集合,需要使用数组的from方法转换成真数组 ,

      • 运用场景:为无序可重复的数组 去重
    • 对象的简化写法

      • 如:在对象中key与value 同名可以只写key
      • 在对象中value是 :function 可以省略 :function
  3. 介绍下 set、Map的区别

    • set应用于数组去重,Map用于数据的储存
    • set 容器是无序不重复的集合体
    • Map本质上是健值对的集合,键可以是任意类型,可以遍历可以跟各种数据格式转换

推荐阅读