ES6&TS重点语法学习

2021-03-03  本文已影响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.特殊类型

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

上一篇下一篇

猜你喜欢

热点阅读