玩转ES6就是这么简单

潮流虽然太快,但我们不停下学习的步伐,就不会被潮流丢下的,下面来领略下ES6中新特性,一睹新生代JS的风采。

1,let和const

  • let和const都是块级作用域,说白了只要是在{}里面的代码块就是let和const的作用域。下面我们分别了解一下它们。
  1. let
  • let 的作用域是在它所在当前代码块,但不会被提升到当前函数的最顶部。如下:
    function f(){
        console.log(test)
        let test = "Hello,World"
    }
    f()
    //这时会报错test is not defined
复制代码
  1. const
  • const 声明的变量必须提供一个值,而且会被认为是常量,意思就是它的值被设置完成后就不能再修改了。如下:
    const name = "zhangsan"
    name = "lisi"
    //再次赋值会报错
复制代码
  • 如果 const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址不能改变,而变量成员是可以修改的。
    const student = {name:"zhangsan"}
    student.name = "lisi"
    console.log(student)
    //这时就不会报错了
复制代码

2,字符串

  1. 模板字符串
  • ES6模板字符简直是开发者的福音啊,解决了 ES5 在字符串功能上的痛点。
  • 第一个用途,基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定。
    var w = " World"
    console.log(`Hello${w}`)
复制代码
  • 第二个用途,ES6反引号(``)来做多行字符串或者字符串一行行拼接。
    var name = "张三"
    var age = 18
    console.log(`我叫${name},今年${age}了。`)
复制代码
  1. trim
  • 除去字符串空格的。
  • trim 左右空格都是去掉。
  • trimLeft 左空格去掉。
  • trimRight 右空格去掉。
    var str = " a ab abc "
    str.trim()
复制代码
  1. repeat
  • 重复字符串的值。
    var str = "123456"
    str.repeat(10)
    //此时重复str中的值10遍
复制代码
  1. includes
  • 判断字符串中是否有需要的字符。
    var str = "abc def"
    str.includes('c d')
    //此时输出结果为true
复制代码
  1. startsWith
  • 判断字符串是不是以此开头。
    var str = "abc def"
    str.startsWith("abc")
    //此时输出结果为true
复制代码
  • endsWith判断字符串是不是以此结尾和startsWith用法一样
  1. padStart
  • 直接看例子,例子中解释。
    var str = "abc def"
    str.padStart(15,"*")
    //输出结果是"********abc def"
    //意思是字符串输出15个字符,不够15个在字符串前面补上*
复制代码
  • padEnd和padStart用法一样,只不过是在后面补够一定数量的字符
  • 字符串的扩展在ES6中还有很多,在这不一一列举了。

3,函数

  1. 函数默认参数
  • ES6为参数提供了默认值。在定义函数时便初始化了这个参数,以便在参数没有被传递进去时使用。
    function f(num = 200){
        console.log(num)
    }
    f(0)//0
    f()//200
    f(300)//300
复制代码
  1. 箭头函数
  • ES6很有意思的一部分就是函数的快捷写法。也就是箭头函数。箭头函数有最直观的三个特点。
  • (1)不需要 function 关键字来创建函数
  • (2)省略 return 关键字
  • (3)继承当前上下文的 this 关键字
    //例如
    [1,2,3,].map(x => x+1)
    //等同于
    [1,2,3].map((function(x){
        return x + 1    
    }).bind(this))
    //当你的函数有且仅有一个参数的时候,是可以省略掉括号的。
    //当你函数返回有且仅有一个表达式的时候可以省略{} 和 return。
复制代码

4,数组——ES6中的扩展

  1. Array.from()
  • 这个方法是Array构造器的静态方法。作用:将把类数组对象转成真正的数组。
  • 格式1:Array.from(类数组对象);
  • 格式2:Array.from(类数组对象,function(item,index){return;})
    var lis = document.getElementsByTagName("li");
    console.log(Array.isArray(lis))/结果false,判断不是真数组
    var rs = Array.from(lis))
    console.log(Array.isArray(rs))//结果true,判断是真数组
复制代码
  1. Array.of
  • 作用:将一组值转换为数组。与Array.from功能相似,理解用来创建数组。主要目的是弥补构造器Array()的不足。
  • 之前使用new创建数组的痛点:
    var arr = new Array(3);
    console.log(arr);//结果[<3 empty >]
复制代码
  • 使用Array.of来改造,如下:
    var arr = Array.of(3);
    console.log(arr);//结果[3]
复制代码
  1. find和findIndex
  • find:用于找出第一个符合条件的数组元素。找不到则是 undefined 。注意,它是不会返回多个,只找一个,找到了就返回。如果你要把所有的满足条件的数组元素素都找出来,你应该用filter()。
  • findIndex:返回第一个符合条件的数组元素的索引。找不到则是-1;
  • 格式:arr.find(function(item,index){ Return 条件;})
    let arr = [
        {name:"zhangsan",score:90}
        {name:"lisi",score:80}
    ]
    let rs = arr.find(item => item.name == "zhangsan")
    let rs1 = arr.findIndex(item => item.name == "zhangsan")
    console.log(rs)//输出{name:"zhangsan",score:90}
    console.log(rs1)//输出0
复制代码
  1. includes
  • 作用:判断元素是否在数组中存在(关于字符串的上面有列举)。返回值是true|false
    let myarr = [1,2,3]
    myarr.includes(1);//true
    myarr,includes("a");//false
复制代码
  • indexOf也可以做类似的工作:(返回索引)
    let myarr = [1,2,3]
    myarr.indexOf(1);//0
    myarr,indexOf("a");//-1,找不到的返回-1
复制代码
  • 有一点要注意indexOf对NaN的判断是错误的,如下:
    [NaN,1,2,3].indexOf(NaN);//-1
复制代码
  • NaN也比较奇怪,他自己不全等于他自己,如下:
    NaN === NaN;//false
复制代码
  • 但是includes对NaN的判断是比较准确的,如下;
    [NaN,1,2,3].includes(NaN);//true
复制代码
  1. fill
  • 作用:给数组填充指定值。fill方法用于空数组的初始化非常方便。已有数据会被覆盖。fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
  • 格式1:arr.fill(值)
  • 格式2:arr.fill(值,起点,终点)包括起点,不包括终点
    let arr = new Array(3);
    arr.fill("*")
    console.log(arr)//输出['*','*','*']
复制代码
  • 覆盖之前的元素,如下:
    let arr = [1,2,3];
    arr.fill("*")
    console.log(arr)//输出['*','*','*']
复制代码
  • 还可以指定填充的位置,如下:
    let arr = new Array(5);
    arr.fill("*",0,2)
    console.log(arr)//输出['*','*',<3 empty items>]
复制代码
  1. 扩展运算符(...)
  • 功能:把数据结构转成数组。
    var arr = [1,2,3];
    var arr2 = [...arr];
    console.log(arr2);//输出结果[1,2,3]
复制代码
  • 还可以利用扩展运算符,把类数组转成数组,如下:
    <ul>
        <li>1</li>
        <li>1</li>
        <li>1</li>
    </ul>
    <script>
        var lis = document.getElementsByTagName("li");
        var arr = [...lis]
        console.log(Array.isArray(arr))//输出true
    </script>
复制代码
  • 把字符串转成数组,如下:
    var str = "hello";
    var arr = [...str];
    console.log(arr);//输出结果['h','e','l','l','o']
复制代码
  • 还可以利用扩展运算符来合并数组(或对象),如下:
    var arr1 = [1,2];
    var arr2 = [3,4];
    var arr = [...arr1]
    console.log(arr);//输出结果['h','e','l','l','o']
复制代码

5,数组的解构赋值

  • 在ES6允许按照一定的模式,从数组或对象中提取值,对变量进行赋值,这被称为解构。是对变量的赋值,变量的值是数组或对象。
  1. 数组的解构赋值
    let [a,b,c] = [1,2,3]
    console.log(a)//1
    console.log(b)//2
    console.log(c)//3
复制代码
  1. 数组解构赋值中的细节
  • 左右结构不一样。
    let [a,b,c] = [1,2]
    console.log(a)//1
    console.log(b)//2
    console.log(c)//undefined
复制代码
  • 跳过一部分。
    let [a,,c] = [1,2,3]
    console.log(a)//1
    console.log(c)//3
复制代码
  • 默认值。
    let [a = 11,b,c,d = 666] = [1,2,3]
    console.log(a)//1
    console.log(b)//2
    console.log(c)//3
    console.log(d)//666
复制代码
  • 嵌套。
    let [a,b,[c],d] = [1,2,[3],[4]]
    console.log(a)//1
    console.log(b)//2
    console.log(c)//3
    console.log(d)//[4]
复制代码

6,拓展的对象功能

  • 对象初始化简写
  • 键值对重名,ES6可以简写如下:
    function man(name,age){
        return{
            name,//这里简写一个name
            age//这里简写一个age
        }
    }
复制代码
  • ES6可以省略冒号与function,如下:
    var man = {
        name:"zhangsan",
        getName(){//这里省略了冒号和function
            console.log(this.name)
        }
    }
复制代码
  • ES6 对象提供了Object.assign()这个方法来实现浅复制。Object.assign()可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{}。
    const objA = { name: 'cc', age: 18 }
    const objB = { address: 'beijing' }
    const objC = {} // 这个为目标对象
    const obj = Object.assign(objC, objA, objB)

    // 我们将 objA objB objC obj 分别输出看看
    console.log(objA)   // { name: 'cc', age: 18 }
    console.log(objB) // { address: 'beijing' }
    console.log(objC) // { name: 'cc', age: 18, address: 'beijing' }
    console.log(obj) // { name: 'cc', age: 18, address: 'beijing' }

    // 是的,目标对象ObjC的值被改变了。
    // so,如果objC也是你的一个源对象的话。请在objC前面填在一个目标对象{}
    Object.assign({}, objC, objA, objB)
复制代码

7,ES6下的严格模式

  • 之前学习的JS,语法非常灵活,JS中这个灵活的特性,弊大于先利。后来增加了严格模式。使用严格模式的目的:规则,提高编译效率。
  • 启动严格模式:"use strict"
  • (1),严格模式下不能不声明变量
    "use strict"
     a = 110;//此时是错的,运行时会报错
复制代码
  • (2),严格模式下不能用8进制的数字
    "use strict"
     var a = 01;//此时是错的,运行时会报错
复制代码
  • (3),严格模式下不能把函数定义在if语句中
    "use strict"
    if(true){
        function f(){//此时是错的,运行时会报错
             console.log("f...")
        }
    }
    f();
复制代码
  • (4),严格模式下函数不能有重名的形参
    "use strict"
    function f(a,a){//此时是错的,运行时会报错
        console.log("f...")
    }
    f();
复制代码
  • (5),严格模式下arguments不再跟踪形参的变化
    "use strict"
    function f(a,b){
        console.log(a,b)//1 2
        console.log(arguments[0],arguments[1])//1 2
        arguments[0] = 1111;
        arguments[1] = 2222;
        console.log(a,b)//1 2
        console.log(arguments[0],arguments[1])//1111 2222
    }
    f(1,2);
复制代码
  • (6),严格模式下不能function中的this不再指向window,但是全局的变量和函数还是属于window的
    "use strict"
    function f(){
        console.log(this)//undefined
    }
    f();
复制代码
  • (7),严格模式也是有作用域范围的,分整个代码段和函数内。
    a = 111;//这里是正确的
    function f(){
      "use strict"
        b = 111;//这里是在严格模式下,是错误的
    }
    f();
复制代码

8,新的两种数据结构(集合)

  1. Set
  • set和数组差不多,是伪数组,也是一种集合,区别在于:它里面的值都是唯一的,没有重复的。
  • 放一个数组到set中必须上[]
    var s1 = new Set([1,2,3,'true'])
复制代码
  • 放一个对象到set中,使用add来添加
    var s1 = new Set();
    s1.add(1)
    s1.add(2)
    s1.add(3)
    console.log(s1)//Set(3){1,2,3}
复制代码
  • 要遍历上面的s1,不能使用forin,使用forEach或者for of
    var s1 = new Set();
    s1.add(1)
    s1.add(2)
    s1.add(3)
    s1.forEach(item => console.log(item))//竖着1 2 3
    //for(var p of s1){console.log(p)}
复制代码
  • 删除set其中的一个元素
    var s1 = new Set();
    s1.add(1)
    s1.add(2)
    s1.add(3)
    s1.delete(1)
复制代码
  1. Map
  • 它类似于对象,里面存放也是键值对,区别在于:对象中的键名只能是字符串,如果使用map,它里面的键可以是任意值。
  • 在map中放数据
    var a = new Map([[1,"123"],["a",'hello']])
复制代码
  • 使用set进行添加
    var a = new Map([
    [1,"123"],
    ["a",'hello']
    ]);
    a.set(false,"abc")
    a.set([1,2,3],{name:"wangcai"})
复制代码
  • 重复的键会覆盖
    var m = new Map();
    m.set(1,"aaa")
    m.set(1,"bbb")
    console.log(m)//Map(1){1 => "bbb"}
复制代码

9,class

  • 从形式上,向主流的面向对象的语言靠拢。我们之前写对象方式可以用 Class用进行优前面我们都是创建构造器,然后去new构造器,构造器就相当于一个类,在ES6中,就可以使用class来创建对象了。
  1. class创建对象
  • 格式:class类名{constructor(参数){this.属性=参数;}method(){}}
  • (1)class 是关键字,后面紧跟类名,类名首字母大写,采取的是大驼峰命名法则。类名之后是{}。
  • (2)在{}中,不能直接写语句,只能写方法,方法不需要使用关键字。
  • (3)方法和方法之间没有逗号。不是键值对。
  • 使用class声明一个类,如下:
    class NBAPlayer{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
    }
    var p1 = new NBAPlayer("库里""30")
复制代码
  1. 使用extends实现继承
  • 格式:class子类extends父类{constructor(参数){super(参数)this.属性 = 值}}
  • (1)使用 extends 关键字来实现继承。
  • (2)在子类中的构造器constructor中,必须要显式调用父类的 super 方法,如果不调用,则 this 不可用。
  • 使用ES6中的extends来实现继承:
    class NBAPlayer{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
    }
    class MVP extends NBAPlayer{
        constructor(name,age){
            super(name,age)
        }
    }
    var mvp1 = new MVP("库里""30")
复制代码
  1. 类的静态方法(static)
  • 直接通过类名来访问的方法就是静态方法。如:Math.abs();这里的 abs()是静态方法。Array.isArray();isArray()是静态方法。 在方法名前加 static 就可以了。
    class NBAPlayer{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        static jump(){
            console.log("jump...")
        }
    }
    NBAPlayer.jump();
复制代码

10,import和export

  • import导入模块、export导出模块
    //全部导入
    import people from './example'
    //有一种特殊情况,即允许你将整个模块当作单一对象进行导入
    //该模块的所有导出都会作为对象的属性存在
    import * as example from "./example.js"
    console.log(example.name)
    console.log(example.age)
    console.log(example.getName())
    //导入部分
    import {name, age} from './example'
    // 导出默认, 有且只有一个默认
    export default App
    // 部分导出
    export class App extend Component {};
复制代码
  • 导入的时候有没有大括号的区别是什么。下面是我在工作中的总结:
  • 1.当用export,default,people导出时,就用import,people 导入(不带大括号)
  • 2.一个文件里,有且只能有一个export,default。但可以有多个export。
  • 3.当用exportname时,就用import{name}导入(记得带上大括号)
  • 4.当一个文件里,既有一个export default people, 又有多个export name 或者exportage时,导入就用import people, { name, age }
  • 5.当一个文件里出现n多个export导出很多模块,导入时除了一个一个导入,也可以用import * as example

11,Promise

  • 在promise之前代码过多的回调或者嵌套,可读性差、耦合度高、扩展性低。通过Promise机制,扁平化的代码机构,大大提高了代码可读性;用同步编程的方式来编写异步代码,保存线性的代码逻辑,极大的降低了代码耦合性而提高了程序的可扩展性。
  • 说白了就是用同步的方式去写异步代码。
  • 发起异步请求
    fetch('/api/todos')
      .then(res => res.json())
      .then(data => ({ data }))
      .catch(err => ({ err }));
复制代码
  • 当然以上promise的知识点,这个只是冰山一角。需要更多地去学习了解一下。

12,Generators

  • 生成器( generator)是能返回一个迭代器的函数。生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。
  • 这里生活中有一个比较形象的例子。咱们到银行办理业务时候都得向大厅的机器取一张排队号。你拿到你的排队号,机器并不会自动为你再出下一张票。也就是说取票机“暂停”住了,直到下一个人再次唤起才会继续吐票。
  • OK。说说迭代器。当你调用一个generator时,它将返回一个迭代器对象。这个迭代器对象拥有一个叫做next的方法来帮助你重启generator函数并得到下一个值。next方法不仅返回值,它返回的对象具有两个属性:done和value。value是你获得的值,done用来表明你的generator是否已经停止提供值。继续用刚刚取票的例子,每张排队号就是这里的value,打印票的纸是否用完就这是这里的done。
    // 生成器
    function *createIterator() {
        yield 1;
        yield 2;
        yield 3;
    }
    // 生成器能像正规函数那样被调用,但会返回一个迭代器
    let iterator = createIterator();
    console.log(iterator.next().value); // 1
    console.log(iterator.next().value); // 2
    console.log(iterator.next().value); // 3
复制代码
  • 那生成器和迭代器又有什么用处呢?
  • 围绕着生成器的许多兴奋点都与异步编程直接相关。异步调用对于我们来说是很困难的事,我们的函数并不会等待异步调用完再执行,你可能会想到用回调函数,(当然还有其他方案比如Promise比如Async/await)。
  • 生成器可以让我们的代码进行等待。就不用嵌套的回调函数。使用generator可以确保当异步调用在我们的generator函数运行一下行代码之前完成时暂停函数的执行。
  • 那么问题来了,咱们也不能手动一直调用next()方法,你需要一个能够调用生成器并启动迭代器的方法。就像这样子的。
    function run(taskDef) { //taskDef即一个生成器函数
        // 创建迭代器,让它在别处可用
        let task = taskDef();
        // 启动任务
        let result = task.next();
        // 递归使用函数来保持对 next() 的调用
        function step() {
            // 如果还有更多要做的
            if (!result.done) {
                result = task.next();
                step();
            }
        }
        // 开始处理过程
        step();
    }
复制代码
  • 生成器与迭代器最有趣、最令人激动的方面,或许就是可创建外观清晰的异步操作代码。你不必到处使用回调函数,而是可以建立貌似同步的代码,但实际上却使用 yield 来等待异步操作结束。

总结

ES6新特性远不止于此,但对于我们日常的学习来说。这算不上全部,但是能算得上是高频使用了。当然还有很有好玩有意思的特性。让我们一起学习吧!

  • 有什么问题,欢迎不吝赐教!

转载于:https://juejin.im/post/5b6e3a54518825018c4d151e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值