美文网首页
ES6&TS重点语法学习

ES6&TS重点语法学习

作者: 孢子菌 | 来源:发表于2021-03-03 15:16 被阅读0次

    以自己作为客户端RD的视角,列举了一些在实际使用中比较常见,而又比较陌生的语法(主要集中在ES6的特性上),做好一些铺垫和基础。

    介绍

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。在 ES5 的基础上新增了很多特性,完善了自身结构,解决了很多问题,更容易使用了。

    TS - TypeScript,有类型的 JavaScript,通过增加静态类型检查来实现“强类型”特性,是 JavaScript 的超集,也可以通过被编译成低版本的 ES3 兼容所有运行环境。

    TS 出现比ES6早,最初 TS 中添加了很多语法规范和特性,但随着 ES 的版本迭代,TS 的很多语法特性都被追平,目前集中在强类型上,对于客户端或熟悉使用编译型语言的同学来说,这种强类型模式比较熟悉,所以篇幅会比较小。

    下面会先介绍 ES6,在此基础上,再介绍TS额外的部分。

    ES6

    一 变量声明

    之前: var
    现在:let(变量) 和 const(常量)
    var 问题:
    1.var 全局作用域,易出错;let const 块级作用域

    {
        let a = 10; 
        var b =20;
    }
    a //调用失败 let 声明的变量的为局部变量,只在{....}的块作用域生效。
    b //20      var 声明的变量为全局变量,在全局作用域生效
    
    // example 2
    var s = "foo"
    if (true) {
      var s = "bar"
    }
    
    s // s=bar
    

    2.const可定义常量

    const a = 10; 
    a = 20; //再次赋值失败 const创建的变量为常量,一旦声明了就不能改变
    

    二 解构赋值

    变量的解构赋值为ES新推出的特性,指的是ES6允许按照一定的模式从数组或对象中取出值,对变量进行赋值。 如果解构不成功,变量的值就等于undefined。

    # 数组解构
    let [a,b,c]  = [1,2,3]  这种写法称为模式匹配,只要 “两边”  结构一致即可赋值。
    console.log(a) //1
    console.log(b) //2
    console.log(c) //3
    
    # 部分解构不成功
    let [a,b] = [1] 
    console.log(a) //1
    console.log(b) //undefined 部分解构不成功
    
    // 默认值
    let [a,b=3] = [1]
    console.log(a) //1
    console.log(b) //3
    
    # 对象解构
    let node = {            
        sex:'fmale',
        age:10
    }
    let {sex,age} = node;
    console.log(sex) //fmale 对象解构,对于内置对象同样可以。
    console.log(age) //10
    
    # 函数参数的解构赋值
    function add([x,y]){
        return x + y;
    }
    let value = add([1,2,3,4,5,6]) 
    value //3 函数的参数解构赋值  形容 let [x,y] = [1,2,3,4,5,6]
    
    # 数值的解构赋值
    let [a,b,c] = 123
    console.log(a) //1 数值解构
    console.log(b) //2
    console.log(c) //3
    
    # 字符串的解构赋值
    let [a,b,c] = '123';
    console.log(a) //1
    console.log(b) //2
    console.log(c) //3
    
    //原则上 只要两边的结构一致都可以进行解构赋值。
    

    三 函数

    箭头函数

    去掉function,用箭头链接方法体

    1. 有且仅有一个参数,()可以不写
    2. 如果有且只一个语句,return 和 {}可以不写
    let a = function(x){
      return x * 2
    }
    a(4) // 8
    
    // 变化1
    let a = (x)=>{
      return x * 2
    }
    a(4) // 8
    
    // 变化2
    let a = x=>{
      return x * 2
    }
    a(4) // 8
    
    // 变化3
    let a = x=> x * 2
    a(4) // 8
    
    // 作为回调,在入参中简洁表达
    setTimeout(() => {
        // to do
    }, 500)
    

    this

    js 里 this 使用非常复杂,就不展开说。直接说结论:
    普通函数里 this 在函数调用时才被赋值,this 等于函数执行时候的执行环境;
    使用箭头函数时,this 等于定义时的环境;
    详见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions

    四 参数扩展

    打开参数

    数组展开

    var arr = [1, 2, 3];
    var arr2 = [...arr]; // ...arr 等价 [1,2,3]
    arr2.push(4);
    console.log(arr2)// [1, 2, 3, 4]
    

    json展开

    let obj1 = {
      foo: 'bar',
      x: 42
    };
    let obj2 = {
      foo: 'new bar',
      y: 13
    };
    let clonedObj = { ...obj1 };
    let mergedObj = { ...obj1, ...obj2 }; // merge 后加的参数会覆盖先加入的参数
    console.log(clonedObj) // {foo: "bar", x: 42}
    console.log(mergedObj) // {foo: "new bar", x: 42, y: 13}
    

    收集参数

    函数的剩余参数

    function add(a,...values){
        var total = 0;
        for(var val of values){
            total +=val;
        }
        return total;
    }
    add(1,2,3,4,5); //2+3+4+5 = 14
    

    五 数组的操作方法

    这里记录的很全: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

    挑几个常见的说下:
    map() 映射 一一对应
    reduce() 收集 出一个结果
    filter() 过滤 留下一部分
    foreach() 遍历 每一个都访问

    let array = [1, 4, 9, 16];
    
    // pass a function to map
    let map1 = array.map(x => x * 2)
    let map2 = array.reduce((x, y) => x + y)
    let map3 = array.filter(x => x > 4)
    let map4 = array.forEach(x => console.log(x))
    
    console.log(map1);// expected output: Array [2, 8, 18, 32]
    console.log(map2);// 30
    console.log(map3);//  [9, 16]
    console.log(map4);// 1, 4, 9, 16
    

    六 字符串模板

    反单引号 `` 围起来字符串,可以动态添加变量

    # 模板字符串中 嵌入变量
    let [a,b] = ['jack','Bob']    
    let text = `hello ${a},I'm ${b}` // 美元符+花括号将变量替换到字符
    text //hello jack, I'm Bob
    
    # 模板字符串中进行逻辑运算
    let [a,b] = [1,2]
    let result = `${a} + ${b} = ${a+b}`
    result //1 + 2 = 3            
    

    七 JSON 序列化操作

    调试的时候很常用,有坑点单独说下。
    JSON.stringify()
    JSON.parse() // 需要标准化的JSON

    // 不是标准化json,key不是字符串
    let json = {
        a:'foo',
        b:'bar',
        c:100
    }
    JSON.stringify(json) //"{"a":"foo","b":"bar","c":100}"
    
    let str = '{"a":"foo","b":"bar","c":100}' 
    // let str = "{'a':'foo','b':'bar','c':100}" key一定要有"双引号",反过来也不行
    JSON.parse(str)
    

    八 异步编程

    异步操作,回调地狱
    代码块

    <script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script>
        let user
        // ajax get请求数据
        $.get('https://api.github.com/users', data=>{
            console.log('fetched all users')
            user = data[0].login
            // 数据校验正确,再请求下一步
            $.get(`https://api.github.com/users/${user}/repos`, data=>{
                console.log('fetched all repos')
                console.log(data)
             })
        })
    </script>
    
    回调地狱

    promise

    作用:进行统一的异步封装

    let promise = new Promise(function (resolve, reject) {
        // 做一些异步操作
        if(/*异步操作成功*/){
            //该value传入回调函数中
            resolve(result);
        }else{
            //该error传入回调函数
            reject(error);
        }
    })
    
    promise.then(result=>{
        console.log(result)
    }).catch(err => {
        console.log(err)
    }).finally(()=>{
      // 最终执行的代码段
    })
    
    //其他
    1.Promise.all(arry)  // all 等待所有异步操作执行完成 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
    2.Promise.race(arry) // race 任一执行完成后就结束 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
    

    再看上面的回调地狱,可以用阶段性返回 promise 对象来解决循环嵌套

    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
    <script>
      axios.get('https://api.github.com/users') // 返回一个 Promise
        .then(reponse => {
          let username = reponse.data[0].login
          // 解析正确返回下一个请求的Promise
          return axios.get(`https://api.github.com/users/${username}/repos`)
        })
        .then(reponse => {
          console.log(reponse.data)
        })
        .catch(err => {
          console.log(err)
        })
    </script>
    

    async/await

    更直观的语法,将异步变同步,ES2017(es8)

    async function myFetch() {
      let reponse = await axios.get('https://api.github.com/users') // 返回一个 Promise
        let username = reponse.data[0].login
      let repos = await axios.get(`https://api.github.com/users/${username}/repos`)
        
      // 操作 repos ...
    }
    

    async/await 原理:可以将函数执行暂停,通过将函数切换成多个小函数来实现。
    更多参考:https://developer.mozilla.org/zh-CN/docs/learn/JavaScript/%E5%BC%82%E6%AD%A5/Async_await

    九 模块

    导出 export:独立模块的对象、函数、值是无法被其他文件访问到的,如果要让外部访问到,需要使用 export 导出
    相对的,要使用其他模块内容,就需要导入 import 相关内容

    // module "my-module.js"
    function cube(x) {// 函数
      return x * x * x;
    }
    
    const foo = Math.PI + Math.SQRT2;// 常量
    
    var graph = {
        options: {
            color:'white',
            thickness:'2px'
        },
        draw: function() {
            console.log('From graph draw function');
        }
    }
    export { cube, foo, graph };
    
    // --------------- another file ---------------
    import { cube, foo, graph } from 'my-module.js';
    
    graph.options = {
        color:'blue',
        thickness:'3px'
    };
    
    graph.draw();
    console.log(cube(3)); // 27
    console.log(foo);    // 4.555806215962888
    

    此外还有默认导出,即我们在 vue 里常见的 export default ,只是将当前模块做默认导出,没有其他特殊含义。

    // module "my-module.js"
    export default function cube(x) {
      return x * x * x;
    }
    
    // --------------- another file ---------------
    import cube from './my-module.js';
    console.log(cube(3)); // 27
    

    TS
    列举下实际开发中,常遇见的TS里有的,但是 ES6 所没有的特性,总结下来就是:

    1. 类型(核心)
    2. 面向对象增强
      这里只是简单列举,一些细节和JAVA或OC使用都类似,如果遇到报错,再查文档 https://www.tslang.cn/docs/handbook/basic-types.html 找找原因,会比较好懂

    一 类型

    1.强类型

    不同于大部分编译型语言,TS 的类型是写在变量名后面,通过冒号: 连接的

    const name:String = "Hello World"
    

    TypeScript 里也有现代语言都具备的类型推断特性(Java要10以上的版本),不需要每一个变量都声明类型。

    2.支持联合类型

    多种类型用竖线 | 连接,表示该变量可以是多种类型的

    function padLeft(value: string, padding: string | number) {
        // ...
    }
    function getSmallPet(): Fish | Bird {
        // ...
    }
    

    3.元组

    swift 里也有,允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组。

    let x: [string, number] = ['hello', 10];
    

    4.枚举

    这个都懂

    enum Color {Red, Green, Blue}
    

    5.特殊类型

    • any —— 表示任何类型
    • void —— 表示没有类型,用于修饰函数返回值类型,作为变量类型时,没有什么用
    • never —— 表示的是那些永不存在的值的类型,和 null 或 undefined 不同,他用来表示类型,而不是具体的值

    6.函数类型

    在基础函数上,多了入参类型和返回值类型

    //函数类型(入参的类型,返回值类型): 返回值类型 
    function(x: number, y: number): number { 
      // 函数体
      return x + y; 
    };
    

    声明一个函数的变量 myAdd ,也需要指定这个函数的类型,函数类型比较复杂点,分成入参类型和返回值类型。
    (入参1:入参1类型, 入参2:入参2类型) => 返回值类型

    代码块

    // 变量名    函数类型(入参的类型,返回值类型)   =    入参的类型(俩 number)         返回值类型   函数体
    let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
    // 定义太长了,不写,也可以通过推断得出
    let myAdd = function(x: number, y: number): number { return x + y; };
    
    // 箭头函数基本没变,入参加了类型
    let double = (e: number) => { return e * 2}
    

    推断文档:https://www.tslang.cn/docs/handbook/type-inference.html

    二 面向对象

    1.接口

    这个JAVA开发太熟悉了,但是在TS里,他更多的是用来创建 Model 数据模型

    interface LabelledValue {
      label: string;
    }
    
    function printLabel(labelledObj: LabelledValue) {
      console.log(labelledObj.label);
    }
    

    加上可选,这种感觉就更明显了

    interface SquareConfig {
      color?: string;
      width?: number;
    }
    

    2.类的Field支持修饰符

    public 、private 、protected 这些老朋友不用多做介绍,再来个 readonly,相当于 final。

    class Demo {
      private a: string;
      public b: string;
      protected c: string;
      readonly name: string; //相当于Java里的final,在初始化或构造函数里一定要被初始化,至多赋值一次
    }
    

    3.抽象类

    abstract class Animal {
        abstract makeSound(): void;
        move(): void {
            console.log('roaming the earch...');
        }
    }
    

    参考内容

    ES6:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference
    TS手册:https://www.tslang.cn/docs/handbook/basic-types.html
    TS参考: https://zhuanlan.zhihu.com/p/98709371

    相关文章

      网友评论

          本文标题:ES6&TS重点语法学习

          本文链接:https://www.haomeiwen.com/subject/jaiqqltx.html