17

ES6 语法讲解


ECMAScript是JavaScript的标准(语法规范),javascript用于遵循这个规范。

  • ES6并不是兼容所有浏览器,需要使用Babel转为ES5语法(ES5语法所有浏览器都兼容)。
  • Visual Studio Code下载插件:Bracket pair Colorizer(颜色高亮)、JavaScript(ES6)code(es6语法提示)、live server(vscode保存代码后,页面立即刷新,不需要手动刷新页面)

注: live server使用:

vscode编辑器页面中右击,选择 “Open with live server”,即可开启保存后就刷新页面的效果,在vscode编辑器最底部有“port:5500”,点击后即可关闭此功能。

1、数组方法

迭代器函数:
(1)、forEach

应用场景:

//forEach使用姿势一:
var numbers = [1, 2, 3, 4, 5],
    sum = 0;
    numbers.forEach(function(item) {
    sum += item;
});
console.log(sum); //结果:15

//forEach使用姿势二:
var numbers = [1, 2, 3, 4, 5],
  sum = 0;
function adder(item) {
  sum += item;
}
//直接调用adder函数,注意不加括号
numbers.forEach(adder);
console.log(sum); //结果:15

注意:map和forEach区别是:map有返回值,而forEach没有返回值。

(2)、map
注:map需要返回值,如果不给return,默认返回undefined,map返回的是一个新数组。

应用场景1:假定有一个数值数组A,将A数组的数值以双倍的形式放到B数组。

var numbers = [1, 2, 3];
var newNumbers1 = numbers.map(function(item) {
  return item * 2;
});
console.log(newNumbers1); // 结果:[2,4,6]

应用场景2:假定有一个对象数组A,将A数组中对象某个属性的值存储在B数组中。

var cars = [
  {
    model: "mini",
    price: 200
  },
  {
    model: "nio",
    price: 300
  }
];
var prices = cars.map(function(item) {
  return item.price;
});
console.log(prices); //结果:[200, 300]
(3)、filter

应用场景1:假定有一个对象数组A,获取数组中指定类型的对象放到B数组中。

var products = [
  {
    name: "cucumber",
    type: "vegetable"
  },
  {
    name: "apple",
    type: "fruit"
  },
  {
    name: "orange",
    type: "fruit"
  }
];
var filters = products.filter(function(item) {
  return item.type == "fruit";
});
console.log(filters); 
//结果:[{name: "apple", type: "fruit"},{name: "orange", type: "fruit"}]

应用场景2:假定有一个对象数组A,过滤掉不满足一下条件的对象,条件:水果 ,价格小于10,数量大于0。

var products = [
  {
    name: "cucumber",
    type: "vegetable",
    quantity: 10,
    price: 5
  },
  {
    name: "apple",
    type: "fruit",
    quantity: 0,
    price: 5
  },
  {
    name: "orange",
    type: "fruit",
    quantity: 1,
    price: 2
  }
];
var filters = products.filter(function(item) {
  //使用&符号将条件链接起来
  return item.type === "fruit" && item.quantity > 0 && item.price < 10;
});
console.log(filters);
//结果:[{name: "orange", type: "fruit", quantity: 1, price: 2}]

应用场景3:假定有对象A和数组B,根据A中id值,过滤掉B中不符合的数据。

var post = { id: 1, title: "A" };
var comments = [
  { postId: 3, content: "CCC" },
  { postId: 2, content: "BBB" },
  { postId: 1, content: "AAA" }
];
function commentsPost(post, comments) {
  return comments.filter(function(item) {
    return item.postId == post.id;
  });
}
console.log(commentsPost(post, comments));
//结果:[{postId: 1, content: "AAA"}],返回的是数组

注意:filter和find区别:filter返回的是数组,find返回的是对象。

(4)、 find

应用场景1:假定有一个对象数组A,找到符合条件的对象

var users = [
  { name: "jack", age: 12 },
  { name: "alex", age: 15 },
  { name: "eva", age: 20 }
];
var user = users.find(function(item) {
  return (item.name = "eva");
});
console.log(user);
//结果:{ name: "eva", age: 20 }
注:find()找到第一个元素后就不会在遍历其后面的元素,所以如果数组中有两个相同的元素,他只会找到第一个,第二个将不会再遍历了。

应用场景2:假定有一个对象数组A,根据指定对象的条件找到数组中符合条件的对象。

var post = { id: 1, title: "AAA" };
var comments = [
  { postId: 3, content: "CCC" },
  { postId: 2, content: "BBB" },
  { postId: 1, content: "AAA" }
];
function commentsPost(post, comments) {
  return comments.find(function(item) {
    return item.postId == post.id;
  });
}
console.log(commentsPost(post, comments));
//结果:{postId: 1, content: "AAA"},返回的是对象
(5)、every
总结:一假即假 ,而且只要有一个元素是假,其后面的元素将不再遍历。
(6)、some
总结:一真即真
使用场景:假定有几台电脑,判断其操作系统是否都大于16
var computers = [
  { name: "mac", ram: 32 },
  { name: "mac", ram: 8 },
  { name: "IBM", ram: 16 },
  { name: "IBM", ram: 64 }
];
var everyComputerCan;
var someComputerCan;
//判断每一个元素的ram是否都大于16
var everyBoolan = computers.every(function(item) {
  return item.ram > 16;
});
//判断元素的ram是否都大于16
var someBoolean = computers.some(function(item) {
  return item.ram > 16;
});
console.log(everyBoolan); //结果:false
console.log(someBoolean);//结果: true
(7)、reduce

应用场景1:计算数组中所有值总和

var numbers = [1, 2, 3];
var sumVal = numbers.reduce(function(sum, number) {
  return sum + number;
  //0是sum的初始化值
}, 0);
console.log(sumVal);

应用场景2:将对象数组中对象的某个属性抽离到另外一个数组中

var colors = [
  { color: "red" }, 
  { color: "green" }, 
  { color: "black" }
];
var colorsNew = colors.reduce(function(colorArr, colors) {
  colorArr.push(colors.color);
  return colorArr;
}, []);
console.log(colorsNew);
//结果:["red", "green", "black"]

应用场景3:判断字符串中括号是否对称

function balanceParents(string) {
  return !string.split("").reduce(function(previous, char) {
    if (char == "(") {
      return ++previous;
    }
    if (char == ")") {
      return --previous;
    }
    return previous;
  }, 0);
}
console.log(balanceParents("(())aaadsd))"));//结果:false

2、新语法

(1)、 const

const 定义的常量后不能更改其值,但是数组是可以创建后,添加元素的。

const arr = [];
arr[0] = 1;//不会报错
console.log(arr);

const str = "abc";
str = "ddd";//报错:Assignment to constant variable.
(2)、模板字符串
定义:模板字符串是指在js语句中使用``符号包含的字符串。
let age = 10;
function makeUppercase(item) {
  return item.toUpperCase();
}
 //模板字符串中语法:
//在模板字符串中使用${方法名()}调用某得方法
//在模板字符串中使用${}获取变量的值
var template = `<h1>内容</h1>
  <spn>${makeUppercase("hello")}</spn>
  <p>${age}</p>`;
document.getElementById("name").innerHTML = template;

页面结果显示:

**内容**
HELLO
10
(3)、箭头函数
const team = {
  merbers: ["heny", "jack"],
  teamName: "A组",
  //箭头函数(ES6语法)
  teamSummary: function() {
    return this.merbers.map(item => {
      //this指向team对象
      return `${item}隶属于${this.teamName}小组`;
    });
  },
  //self保存this(ES5语法)
  teamSummary1: function() {
    let self = this;
    return this.merbers.map(function(item) {
      return `${item}隶属于${self.teamName}小组`;
    });
  },
  //bind绑定this(ES5语法)
  teamSummary2: function() {
    return this.merbers.map(
      function(item) {
        return `${item}隶属于${this.teamName}小组`;
      }.bind(this)
    );
  }
};
console.log(team.teamSummary());
console.log(team.teamSummary1());
console.log(team.teamSummary2());
(4)、 增强对象字面量
目的:减少不必要的代码,比如我们使用vue开发时:
new Vue({
  el: "#app",
  //此处的router就是一种简写形式(即增强对象字面量),其完整写法为:"router:router"
  router,
  components: { App },
  template: "<App/>"
});

同理,对于jquery中的ajax请求:

$.ajax({
 //此处的url和data就是简写形式(即增强对象字面量),完整的为"url:url,data:data"
 url,
 data,
 methods:"POST"
});
(5)、扩展运算符

应用场景1:将单独的数值组成数组返回

//使用"..."(扩展运算符)自动将传入的参数组成数组:numbers
function addNumber(...numbers) {
  return numbers.reduce((sum, item) => {
    return sum + item;
  }, 0);
}
console.log(addNumber(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
//结果:55

应用场景2:组合多个数组

var defaultNum = [1, 2, 3, 4, 5];
var myNum = [10, 20];
var yourNum = [9, 8, 7];
console.log([11, 22, 33, ...defaultNum, ...myNum, ...yourNum]);
//结果: [11, 22, 33, 1, 2, 3, 4, 5, 10, 20, 9, 8, 7]
(6)、 解构

应用场景1:对象属性解构

var obj = {
  name: "Zhangfei",
  age: 26
};
//注意:结构的变量的名字要和对象中的名字保持一致,找不到的将会返回undefined
const { name, age, data } = obj;
console.log(name, age, data);
//结果:Zhangfei  26  undefined

应用场景2:函数参数解构

var obj = {
  name: "zhangsan",
  age: 12
};
function myObj({ name, age }) {
  return `${name},年龄:${age}岁`;
}
console.log(myObj(obj));
//结果:zhangsan,年龄:12岁

应用场景3:数组元素的解构

const names = ["hery", "bucky", "emily"];
const [name1, name2, name3] = names;
console.log(name1, name2, name3);
//结果:demo.js:3 hery bucky emily

应用场景4:数组长度的解构

const names = ["hery", "bucky", "emily"];
//使用{}解析数组得到数组长度
const { length } = names;
console.log(length);

应用场景5:结构和展开运算符搭配使用

const names = ["herry", "emliy", "buky"];
const [name1, name2, ...rest] = names;
console.log(name1);  //herry
console.log(name2);  //emliy
console.log(rest);  //['buky']

应用场景6:将数组转为对象

const points = [[1, 2], [3, 4], [5, 6]];
var newPoints = points.map(function(item) {
  const [x, y] = item;
  return { x, y };
});
console.log(newPoints);
//结果:[{x: 1, y: 2},{x: 3, y: 4},{x: 5, y: 6}]

3、新语法

(1)、 面向对象class(万事皆对象)
class Car {
  constructor(options) {
    this.title = options.title;
  }
  drive() {
    return "vromm";
  }
}
//这里需要继承Car类,拿到构造函数中的title属性
class Toyota extends Car {
  constructor(options) {
    //使用super继承父类的构造函数中的属性,这样toyota.title才不会是undefined
    super(options);
    this.color = options.color;
  }
}
const toyota = new Toyota({ color: "red", title: "MINI" });
console.log(toyota.title); //MINI
(2)、 generator生成器(可以返回多次的函数)
//斐波那契数列
//生成器函数是:在function后面加上*的函数
function* fib(max) {
  var a = 0,
    b = 1,
    n = 0;
  while (n < max) {
    yield a;//yield关键字
    [a, b] = [b, a + b];
    n++;
  }
  return;
}
for (var x of fib(5)) {
  console.log(x);
}
//结果:0 1 1 2 3
(3)、 数据结构:map (与上面所讲的数组的map方法不是一回事)
注:与对象不同的是,键和值可以使任意类型的。

应用场景1: 创建map数据结构

const map1 = new Map();
//设置key键
const key1 = "name",
  key2 = {},
  key3 = function() {};
//设置value
map1.set(key1, "key1‘s value");
map1.set(key2, "key2’s value");
map1.set(key3, "key3‘s value");
console.log(map1.get("name"));  //key1‘s value
console.log(map1.get(key2));   //key2’s value
console.log(map1.get(key3));  //key3‘s value

应用场景2:获取map数据结构的长度

console.log(map1.size); //3

应用场景3:遍历map数据结构的key和value

for(var [key,value] of map1){
    console.log(`${key} = ${value}`);
}
//结果:name = key1‘s value
        [object Object] = key2’s value
        function () {} = key3‘s value
for (let item of map1.keys()) {
  console.log(item);
}
//结果:name         {}           ƒ () {}
for (let item of map1.values()) {
  console.log(item);
}
//结果:key1’s value         key2’s value          key3‘s value

应用场景4:将map数据结构的key和value转为数组

const keyArr = Array.from(map1.keys());
console.log(keyArr);
//结果:["name", {…}, ƒ]
const valueArr = Array.from(map1.values());
console.log(valueArr);
//结果:["key1‘s value", "key2’s value", "key3‘s value"]
(4)、 数据结构:set
set即集合:可以存储任何类型数据,并且是唯一的。

应用场景1:创建set

var set = new Set();
set.add(100);
set.add("asdf");
set.add({ name: "herry" });
set.add("fn");
set.add(100);
console.log(set);

//结果:{100, "asdf", {…}, "fn"}

应用场景2:set长度计算

console.log(set.size);
//结果: 4

应用场景3:判断set中是否包含某项

console.log(set.has(100));
console.log(set.has({ name: "herry" }));
//结果:true   
        false(因为对象在内存中存储的是地址,而不是值,所以是false)

应用场景4:删除set中某元素

set.delete("fn");
console.log(set);
//结果:{100, "asdf", {…}}

应用场景5:遍历set

for (let item of set) {
  console.log(item);
}
//结果:100              "asdf"             {…}   

应用场景6:set转为数组

const arr = Array.from(set);
console.log(arr);
//结果:[100, "asdf", {…}]

4、数据请求(异步)

(1)、 promise
    A[Promise] --> B(unresolved) 
    A[Promise] --> c(resolved) 
    A[Promise] --> d(rejected)
    c --> e[then]
    d --> f[catch]

应用场景1:

let promise = new Promise((resolve, reject) => {
  resolve();
  //   reject();
});
promise
  .then(() => {
    console.log("no problem");
  })  //resolve后走then()方法
  .then(() => {
    console.log("可以无限调用then");
  .catch(() => {
    console.log("uh oh,出问题啦");
  }); //reject后走catch()方法
(2) fetch

fetch方法定义:

①、option(参数选项):

  • method:get | post 等方法
  • headers:任何你想加到请求中的头,可以是对象字面量的方式也可以是通过 Headers
  • body:发送给服务器的信息, 可以是JSON, ufferSource, FormData, URLSearchParams, 或 USVString。注意get和HEAD请求没有body
  • mode:请求模式, 可选值为 cors, no-cors, same-origin, 或 navigate,cors-with-forced-preflight。默认值应该为 cors。但在Chrome中,Chrome 47 之前的版本默认值为 no-cors ,自Chrome 47起,默认值为same-origin。--MDN Request
  • credentials:在请求中是否需要凭据。在请求数据中根据是否需要携带Cookie 来设置其值,可选值为omit(在请求中不懈怠认证凭据(Cookie)), same-origin(在同原站点下包含凭据), 或 include(对所有网站包含认证凭据)
  • cache:如何处理缓存,可取值有 default | no-store | no-cache | reload | force-cache | only-if-cached
  • redirect:对重定向的处理,可取值 follow, error, redirect
  • referrer:一个指定了no-referrer, client, 或一个 URL的 USVString 。默认值是client.
  • integrity: 包括请求的 subresource integrity 值 (e.g., sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).

②、mode 参数便于CORS,设置不同的值可以使在不同的请求方式下,使得请求有效。

  • cors:在同域和带有CORS响应头的跨域下可以请求成功
  • no-cors:常用于在跨域不带CORS场景下,此时请求发出并且会有响应,但是此时type为“opaque”, status为0 ,js获取不到返回数据。
  • same-origin:在同域下请求
  • cors-with-forced-preflight:在请求前进行preflight 检查

应用场景1:fetch实例

let url = "http://jsonplaceholder.typicode.com/posts";
fetch(url)
  .then(response => response.json())  //fetch方法中先获取response.json()
  .then(data => console.log(data))
  .catch(error => console.log(error));
//结果:返回的是接口详细数据

应用场景2:fetch的三种请求数据方式

document.getElementById("button1").addEventListener("click", getText);
document.getElementById("button2").addEventListener("click", getJson);
document.getElementById("button3").addEventListener("click", getInternet);

//获取本地文本数据
function getText() {
  fetch("test.txt")
    .then(res => res.text())
    .then(data => {
      document.getElementById("output").innerHTML = data;
    })
    .catch(error => {
      console.log(error);
    });
}
//获取本地json数据
function getJson() {
  fetch("data.json")
    .then(res => res.json())
    .then(data => {
      console.log(data);
      var str = "";
      data.forEach(function(item) {
        str += `<h2>${item.title}</h2><h3>${item.body}</h3>`;
      });
      document.getElementById("output").innerHTML = str;
    })
    .catch(error => {
      console.log(error);
    });
}
//获取接口数据
function getInternet() {
  fetch("http://jsonplaceholder.typicode.com/users")
    .then(res => res.json())
    .then(data => {
      console.log(data);
      var str = "";
      data.forEach(function(item) {
        str += `<h2>${item.id}</h2><h3>${item.name}</h3>`;
      });
      document.getElementById("output").innerHTML = str;
    })
    .catch(error => {
      console.log(error);
    });
}
//data.json数据
[
  {
    "title": "es6",
    "body": "I am es6"
  },
  {
    "title": "es7",
    "body": "I am es7"
  },
  {
    "title": "es8",
    "body": "I am es8"
  }
]
//test.txt数据
这是本地文本数据测试的!!!

应用场景3:封装fetch(使用ES6语法promise,对照下面ES7语法封装)

//首先封装fetch 方法
class EasyHttp {
  //get方法
  get(url) {
    return new Promise((resolve, reject) => {
      fetch(url)
        .then(rsp => rsp.json())
        .then(data => resolve(data))
        .catch(error => reject(error));
    });
  }
  //post请求
  post(url, data) {
    return new Promise((resolve, reject) => {
      fetch(url, {
        method: "POST",
        headers: {
          "Content-type": "application/json"
        },
        body: JSON.stringify(data)
      })
        .then(res => res.json())
        .then(data => resolve(data))
        .catch(error => reject(error));
    });
  }

  //put请求
  put(url, data) {
    return new Promise((resolve, reject) => {
      fetch(url, {
        method: "PUT",
        headers: {
          "Content-type": "application/json"
        },
        body: JSON.stringify(data)
      })
        .then(res => res.json())
        .then(data => resolve(data))
        .catch(error => reject(error));
    });
  }

  //delete请求
  delete(url) {
    return new Promise((resolve, reject) => {
      fetch(url, {
        method: "DELETE",
        headers: { "Content-type": "application/json" }
      })
        .then(rsp => rsp.json())
        .then(data => resolve("数据删除成功!"))
        .catch(error => reject(error));
    });
  }
}
//main.js数据中调用封装好的fetch方法
const http = new EasyHttp();
//get请求(获取数据)
http
  .get("http://jsonplaceholder.typicode.com/users")
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log(error);
  });

//post请求数据(增加数据)
const data = {
  name: "Herry",
  username: "恒瑞"
};
http
  .post("http://jsonplaceholder.typicode.com/users", data)
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

//put请求(更新数据)
const data = {
  name: "Herry",
  username: "恒瑞"
};
http
  .put("http://jsonplaceholder.typicode.com/users/2", data)
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

//delete请求(删除数据)
http
  .delete("http://jsonplaceholder.typicode.com/users/2")
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

5、es7方法

(1)、 async 和 await

应用场景1:async 和 await基本使用

//使用async定义函数,返回的是一个promise对象
async function myFun() {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Hello"), 1000);
  });
  const error = false;
  if (!error) {
    //这里await等待promise返回结果
    const rsp = await promise;
    return rsp;
  } else {
    await Promise.reject(new Error("error:报错了!"));
  }
}
myFun()
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log(error);
  });
  //输出结果:Hello

应用场景2:async 和 await调用接口

async function getUsers() {
  //await等待接口调用成功
  const response = await fetch("http://jsonplaceholder.typicode.com/users");
  //await等待数据解析成功
  const rsp = await response.json();
  return rsp;
}

getUsers()
  .then(data => console.log(data))
  .catch(error => console.log(error));
//返回结果:users数据信息

应用场景3:ES7语法使用async 和 await重新封装fetch(对照上面的promise封装fetch)

//首先封装fetch方法:
class EasyHttp {
  //get方法
  async get(url) {
    const response = await fetch(url);
    const rspData = await response.json();
    return rspData;
  }
  //post请求
  async post(url, data) {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-type": "application/json"
      },
      body: JSON.stringify(data)
    });
    const rspData = await response.json();
    return rspData;
  }

  //put请求
  async put(url, data) {
    const response = await fetch(url, {
      method: "PUT",
      headers: {
        "Content-type": "application/json"
      },
      body: JSON.stringify(data)
    });
    const rspData = await response.json();
    return rspData;
  }

  //delete请求
  async delete(url) {
    const response = await fetch(url, {
      method: "DELETE",
      headers: { "Content-type": "application/json" }
    });
    const rspData = await response.json();
    return rspData;
  }
}
//main.js数据中调用封装好的fetch方法
const http = new EasyHttp();
//get请求(获取数据)
http
  .get("http://jsonplaceholder.typicode.com/users")
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log(error);
  });

//post请求数据(增加数据)
const data = {
  name: "Herry",
  username: "恒瑞"
};
http
  .post("http://jsonplaceholder.typicode.com/users", data)
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

//put请求(更新数据)
const data = {
  name: "Herry",
  username: "恒瑞"
};
http
  .put("http://jsonplaceholder.typicode.com/users/2", data)
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

//delete请求(删除数据)
http
  .delete("http://jsonplaceholder.typicode.com/users/2")
  .then(data => console.log(data))
  .catch(error => {
    console.log(error);
  });

Miss_Ye
1.5k 声望157 粉丝

知识的价值不在于占有,而在于使用!


引用和评论

0 条评论