ES6新特性语法

330 阅读3分钟

这是我参与更文挑战的第3天,活动详情查看:更文挑战

let&const

var声明的变量往往会越域,但let声明的变量有严格的局部作用域

{
  var a = 1;
  let b = 1;
}
console.log(a); //1
console.log(b); //Uncaught ReferenceError: b is not defined

var可以声明多次,let只能申明一次

var a = 1;
let b = 2;
var a = 3;
let b = 4;
console.log(a); //3
console.log(b); //Uncaught SyntaxError: Identifier 'b' has already been declared

var会提升变量,let不存在变量提升

console.log(a); //undefined
console.log(b); //Uncaught ReferenceError: Cannot access 'b' before initialization
var a = 1;
let b = 2;

const声明常量(只读变量),声明之后不允许改变,一旦声明必须初始化,否则报错。

const a = 1;       
a = 2;
console.log(a); //Uncaught TypeError: Assignment to constant variable.

解构表达式

数组解构

//之前的赋值写法
let arr = ["hello","world","ES6"];
let a = arr[0];
let b = arr[1];
let c = arr[2];
console.log(a,b,c); //hello world ES6

//ES6之后
let [d,e,f] = arr;
console.log(d,e,f); //hello world ES6

let [first] = arr;
console.log(first) //hello

对象解构

// 以前写法
const person = {
  name: "java",
  age: 18,
  friend: ["python,go,php"]
}
const name = person.name;
const age = person.age;
const friend = person.friend;

console.log(name, age, friend); //java 18 ["python,go,php"]

// 对象解构
const {name,age,friend} = person;
console.log(name,age,friend); //java 18 ["python,go,php"]

let {name:n, age:a, friend:f} = person;
console.log(n, a, f)

let {name} = person
console.log(name)

字符串扩展

新增API

ES6为字符串扩展了几个新的API:

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith(): 返回布尔值,表示参数字符串是否在原字符串的尾部。
let a = "hello,world";

console.log(a.startsWith("hello")); //true
console.log(a.endsWith("world")); //true
console.log(a.includes("w")); //true
console.log(a.includes(",")); //true

字符串模板

除此之外还有一个字符串模板,相当于加强版的字符串。用反引号``(之前我们字符串一直使用的是""),可以用来定义多行字符串,还可以在字符串中加入变量和表达式。

let name = "Jam";
let age = 18;
function hello(){
  return "你好";
}
let info = `我是${name},年龄${age+1},${hello()}`;
console.log(info);

函数优化

函数参数默认值

以前写法

function add(a, b){
  b = b || 1;
  return a + b;
}

console.log(add(10));

现在可以直接给一个默认值了

function add(a, b = 1){
  return a + b;
}

console.log(add(10));

不定参数

用来表示不确定参数的个数,必须有且只有一个不定参数。

function fun(...values){
  console.log(values); //本质就是转化为数组
  console.log(values.length); //5
}

fun(4,5,6,7,8); 

箭头函数

将函数简写

var print = function(obj) {
  console.log(obj)
}
// 简写
var print2 = obj => console.log(obj)
print2("hello")

// 多个参数写法
var sum1 = (a, b) => a + b;
var sum2 = (a, b) => {
  c = a + b;
  return c + 100;
}
console.log(sum1(1, 2));
console.log(sum2(1, 2));

// 没有参数时,需要 () 占位,代表参数部分
let sayhello = () => console.log("hello")
sayhello()

const person = {
  name: "java",
  age: 18,
  friend: ["python,go,php"]
}
// 算是省略了 return
var printName = (person) => person.name;
console.log(printName(person)); 

对象新增API

const person = {
  name: "java",
  age: 18,
  friend: ["python,go,php"]
}
//将所有的属性名组成一个数组
console.log(Object.keys(person));
//将所有的属性值组成一个数组
console.log(Object.values(person));
//将属性名和值分别取出来组成一个数组
console.log(Object.entries(person));

const target = {
  a: 1
};
const source1 = {
  b: 2
};
const source2 = {
  c: 3
};
//将source1和source2合并到target
Object.assign(target,source1,source2);
console.log(target);

声明对象简写

let person = {
  name: "Nginx",
  //以前
  play: function (things) {
    console.log(this.name + ": playing:" + things);
  },
  // ES6写法(两种)
  // 箭头函数,拿不到this
  play2: things => console.log(person.name + ": playing:" + things),
  // 简写
  play3(things){
    console.log(this.name + ": playing:" + things);
  }
};
person.play("basketball")
person.play2("game");
person.play3("soccer")

map方法

接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。

let arr = ["1", "10", "15", "99"];
arr = arr.map(item => item + "java");
console.log(arr); //["1java", "10java", "15java", "99java"]

Promise

在JavaScript的世界中,所有代码都是单线程执行的。由于这个 “缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现。一旦有一连串的ajax请求a,b,c,d...后面的请求依赖前面的请求结果,就需要层层嵌套。这种缩进和层层嵌套的方式,非常容易造成上下文代码混乱,我们不得不非常小心翼翼处理内层函数与外层函数的数据,一旦内层函数使用了上层函数的变量,这种混乱程度就会加剧,这种层叠上下文的层层嵌套方式,着实增加了神经的紧张程度。

案例:用户登录,并展示该用户的各科成绩。在页面发送两次请求:

  1. 查询用户,查询成功说明可以登录

  2. 查询用户成功,查询科目

  3. 根据科目的查询结果,获取去成绩

实现:首先我们需要根据需求需要先去创建3个json数据

user.json

{
"id": 1,
"name": "zhangsan",
"password": "123456"
}

user_course_1.json

{
"id": 10,
"name": "chinese"
}

course_score_10.json

{
"id": 100,
"score": 90
}

用过去的方法来实现这个需求

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  </head>
  <body>
    <script>
      // 1、查出当前用户信息
      // 2、按照当前用户的id查出他的课程
      // 3、按照当前课程id查出分数
      $.ajax({
        url: "user.json",
        success(data) {
          console.log("查询用户:", data);
          $.ajax({
            url: `user_course_${data.id}.json`,
            success(data) {
              console.log("查询到课程:", data);
              $.ajax({
                url: `course_score_${data.id}.json`,
                success(data) {
                  console.log("查询到分数:", data);
                },
                error(error) {
                  console.log("出现异常了:" + error);
                }
              });
            },
            error(error) {
              console.log("出现异常了:" + error);
            }
          });
        },
        error(error) {
          console.log("出现异常了:" + error);
        }
      });
    </script>
  </body>
</html>

使用Promise封装,虽然代码比之前更多了,但是逻辑上是比较清晰可取的。

//promise封装异步操作
let p = new Promise((success, error) => {
  $.ajax({
    url: "user.json",
    success: function (data) {
      console.log("查询用户:", data);
      //表示成功后进行执行下一个方法,即后面的p.then
      success(data);
    },
    error: function (err) {
      console.log("出现异常了:" + error);
      error(err);
    }
  });
});
p.then((obj) => {
  //继续用promise包装,因为后面还有第3个需求
  return new Promise((success, error) => {
    $.ajax({
      url: `user_course_${obj.id}.json`,
      success: function (data) {
        console.log("查询到课程:", data);
        success(data);
      },
      error: function (err) {
        console.log("出现异常了:" + error);
        error(err);
      }
    })
  })
}).then((obj) => {
  $.ajax({
    url: `course_score_${obj.id}.json`,
    success(data) {
      console.log("查询到分数:", data);
    },
    error(error) {
      console.log("出现异常了:" + error);
    }
  });
}).catch((err => {
  console.log(err);
}))

当然,上面的代码量多,而且实际开发我们也不会这么做,下面我们去把他封装成函数。

function get(url) {
  return new Promise((success, error) => {
    $.ajax({
      url: url,
      success: function (data) {
        success(data);
      },
      error: function (err) {
        error(err);
      }
    })
  });
}

get("user.json")
  .then((data) => {
  console.log("查询用户:", data);
  return get(`user_course_${data.id}.json`);
})
  .then((data) => {
  console.log("查询到课程:", data);
  return get(`course_score_${data.id}.json`)
})
  .then((data) => {
  console.log("查询到分数:", data);
})
  .catch((err)=>{
  console.log("出现异常了:" , error);
})

模块化

模块化就是把代码进行拆分,方便重复利用。类似java中的导包:要使用一个包,必须先导包。而JS中没有包的概念,换来的是模块

模块功能主要由两个命令构成: exportimport

export :命令用于规定模块的对外接口。 import :命令用于导入其他模块提供的功能。

举个例子:

导出一个函数和一个变量->hello.js

const util = {
  sum(a, b){
    return a+b;
  }
};

var name = "java";

//导出util对象
export {util};
//导出name对象
export {name};

导出来使用,main.js

import {name, util} from "./hello.js";
console.log(name);
util(1,2);