撩课-Web架构师养成系列(第一篇)-ES6/7/8

前言html

Web架构师养成系列共15篇,每周更新一篇,主要分享、探讨目前大前端领域(前端、后端、移动端)企业中正在用的各类成熟的、新的技术。前端

部分文章也会分析一些框架的底层实现,让咱们作到知其然知其因此然。es6

探讨、交流、资料获取请加我微信yejh9522ajax

本篇文章阅读须要时长:约15分钟后端

1、ECMAScript 6/7/8简介数组

ECMAScript 6.0,简称ES6,第一个版本是在2015年6月进行发布,因此也称之为《ECMAScript 2015 标准》(简称 ES2015)。浏览器

JavaScript是ECMAScript的一种实现(分支),遵循ECMAScript标准的。目前主流浏览器已经能够完美兼容和使用ES6。ES7/8部分新特性也已经被用于咱们的实际开发中。bash

image

本篇主要讲解ES6的知识点,内容以下:let和const、解构赋值、字符串操做、函数、数组API、集合、对象拷贝、延展操做符、对象补充、Generator、Proxy、Reflect。微信

2、let和const网络

ES6新增了let和const来声明变量,主要是解决var声明变量所形成的困扰和问题:

var不能用于定义常量
  
  var能够重复声明变量
  
  var存在变量提高
  
  var不支持块级做用域
复制代码

而let和const解决了以上问题,具体操做以下:

1)不能够重复声明变量

let site = 'itLike';
let site = 'itLike';
console.log(site);
复制代码

运行结果:

Identifier 'site' has already been declared
复制代码

2)不存在变量提高

console.log(site);
复制代码
let site = 'itLike';
运行结果:
 site is not defined
复制代码

3)能够定义常量

不能给常量从新赋值,但若是是引用类型的话能够进行修改。

// 天然对数的底
const E = 2.718;
E = 2.71;
console.log(E);
运行结果:
Assignment to constant variable.

//引用类型
const LK = {
 name:'itLike',
 intro: '喜欢IT, 就上撩课(itLike.com)'
};

LK.name = '撩课';
console.log(LK);

运行结果:
复制代码

image

4) 块级做用域

若是用var定义变量,变量是经过函数或者闭包拥有做用域;但,如今用let定义变量,不只仅能够经过函数/闭包隔离,还能够经过块级做用域隔离。

块级做用域用一组大括号定义一个块,使用 let 定义的变量在大括号的外部是访问不到的,此外,let声明的变量不会污染全局做用域。

{let site = 'itLike';}
console.log(site);
复制代码

运行结果:

site is not defined
if(1){let str = '小撩';}
console.log(str);

运行结果:
str is not defined
复制代码

5)案例运用

高级排他实现(再也不使用闭包)

image

3、解构赋值

用于分解js中对象的结构。

1) 用于数组的结构

// 普通写法
let nameArr = ['撩课', '小撩', '小煤球'];
let name1 = nameArr[0];
let name2 = nameArr[1];
let name3 = nameArr[2];

// 解构写法
let [name1, name2, name3] = nameArr;
console.log(name1, name2, name3);
复制代码

2)对象的解构

// 写法1
let {name, age, sex}= {name: '小煤球', age: 1, sex: '公'};
// 结果: 小煤球 1 公
console.log(name, age, sex);

// 写法2: 解构重命名
let {name: lkName, age: lkAge, sex: lkSex}
= {name: '小煤球', age: 1, sex: '公'};
// 结果: 小煤球 1 公
console.log(lkName, lkAge, lkSex);

// 写法3:能够设置默认值
let {name, age, sex = '公'}
= {name: '小煤球', age: 1};
console.log(sex);  // 公

// 写法4:省略解构
let [, , sex] = ['小煤球', 1, '公 '];
console.log(sex);
复制代码

3) 应用场景

在封装ajax的GET和POST请求时, 就能够运用到解构的知识点,代码以下:

image

4、延展操做符

1)延展数组

let arr1 = [ 'a', 'b', 'c'];
  let arr2 = [1, 2, 3];
  let result = [...arr1, ...arr2];
  console.log(result);
  // [ "a", "b", "c", 1, 2, 3 ]
复制代码

2)延展对象

let smallDog = {name:'小煤球', age: 1};
  let bigDog = {name: 'Python', age: 2};
  let dog = {...smallDog, ...bigDog};
  console.log(dog);
  // {name: "Python", age: 2}
复制代码

注意: 若是对象中的属性一致, 会被覆盖

3)开发应用场景

function getMinValue() {
    console.log(Math.min(...arguments));
  }
  
  getMinValue(1, -99, 22, 10, 9); // -99
复制代码

5、字符串操做 新增字符串方法

1) startsWith()

判断字符串是否以 XX 开头
let url = 'http://www.itlike.com';
console.log(url.startsWith('http')); // true
复制代码

2) endsWith()

判断字符串是否以 XX 结尾
let file = 'index.html';
console.log(file.endsWith('html')); // true
复制代码

3) includes()

判断字符串中是否包含 XX
let str = 'liaoke';
console.log(str.includes('ao')); // true
复制代码

4) repeat()

拷贝n份
let title = '撩课在线';
console.log(title.repeat(100));
复制代码

5) padStart() / padEnd()

padStart()用于头部补全,
padEnd()用于尾部补全;
第一个参数用来指定字符串的最小长度,
第二个参数是用来补全的字符串。

// "2030111111"
let y1 = '2030'.padEnd(10, '1');

// "2030-11-22"
let y2 = '11-22'.padStart(10, '2030-MM-DD');

console.log(y1, y2);
复制代码

模板字符串

1) 模板字符串

模板字符串用反引号(`)包含,变量用${}括起来; 在开发中使用是很是灵活的。

let name = '小煤球';
 let sex = '公';
 let result = `我叫 ${name} , 我是 ${sex} 的`;
console.log(result);
// 我叫 小煤球 , 我是 公 的
复制代码

2) 模板字符串遍历插入

image

3) 模板字符串实现原理

let name = '小煤球';
let sex = '公';
let result = `我叫 ${name} , 我是 ${sex} 的`;
result = result.replace(/\${([^}]*)}/g);
console.log(result);
复制代码

6、函数操做

1) 设置默认参数

function logPerson(name, sex = '男', age = 20) {
console.log(name);
console.log(sex);
console.log(age);
}

// undefined 男 20

logPerson();
复制代码

2)延展参数转化

let logName = function (arg1, ...arg2) {
 console.log(arg1, arg2);
};
// 宋小宝 , ["赵薇", "王菲", "那英"]
logName('宋小宝', '赵薇', '王菲', '那英');
复制代码

3)箭头函数

箭头函数简化了函数的的定义方式; 通常以 "=>" 操做符左边为输入的参数; 而右边则是进行的操做以及返回的值 inputs => output。

["赵薇", "王菲", "那英"].forEach(
 val => console.log(val)
 );
复制代码

注意:

1)多个参数要用()包起来,函数体有多条语句须要用{}包起来; 2)箭头函数根本没有本身的this,因此内部的this就是外层代码块的this。 正是由于它没有this,从而避免了this指向的问题; 3)箭头函数中没有arguments对象。

image

注意:

1)let声明的变量不会放在window上 2)对象不是做用域

let site = 'like.com';
 let obj = {
    site: '撩课',
    func: () => {
      // this指向window
      console.log(this);
      // undefined
      console.log(this.site);
     }
 };

let func = obj.func;
func();
复制代码

7、数组新增方法

ES6中在原有数组的方法上又新增了一些好用的方法,好比:forEach、findIndex、find、map、reduce、filter、every、some等。

1)Array.from()

将一个数组或者类数组变成新数组,是浅拷贝操做。

let oldArr = ['小煤球', 10, {df1: '小Python', df2: '土豆'}];
let newArr = Array.from(oldArr);
console.log(newArr === oldArr); // false
复制代码

2)Array.of()

建立一个具备可变数量参数的新数组实例,而不考虑参数的数量或类型。

// [8]
  console.log(Array.of(8));
  // [1, 2, 3]
  console.log(Array.of(1, 2, 3));
  // [ , , , , , , ]
  console.log(Array(8));
  // [1, 2, 3]
  console.log(Array(1, 2, 3));
复制代码

3)Array.fill()

用一个固定值填充一个数组中从起始索引到终止索引内的所有元素。 语法结构:arr.fill(value[, start[, end]])

let array1 = [1, 2, 3, 4, 5];
  // 用 撩 替换 索引[2,5]中的内容
  console.log(array1.fill('撩', 2, 5));
  // 用 撩 替换 索引[1]中的内容
  console.log(array1.fill('撩', 1));
  // 用 撩 替换 数组中全部内容
  console.log(array1.fill('撩'));
复制代码

运行结果:

image

8、对象操做 8.1 属性简写

若是对象中属性值和变量名同样,而且属性的值就是变量表示值,则简写。

image

8.2 super

经过super能够调用prototype上的属性或方法。

image

** 8.3 Object.is **

对比两个值是否相等

> console.log(Object.is(Array, Object));
复制代码

8.4 Object.setPrototypeOf

将一个指定的对象的原型设置为另外一个对象或者null

let dog1 = { name: '小煤球' };
  let obj = {name: 'xxx'};
  Object.setPrototypeOf(dog1, obj);
  let dog2 = {
     __proto__: obj
  };
  console.log(dog1.__proto__.name);
  console.log(dog2.__proto__.name);
复制代码

8.5 对象拷贝-深拷贝和浅拷贝

1)浅拷贝

Object.assign拷贝
  
  let obj1 = { dog1: { name: '小煤球' } };
  let obj2 = { name: '小Python' };
  let obj = {};
  Object.assign(obj, obj1, obj2);
  console.log(obj);

  延展拷贝
  
  let obj1 = { dog1: { name: '小煤球' } };
  let obj2 = { name: '小Python' };
  console.log({ ...obj1, ...obj2 });
复制代码

2)深拷贝

JSON.parse和JSON.stringify
 
  let obj1 = { dog1: { name: '小煤球' } };
  let obj2 = { name: '小Python' };
  console.log(JSON.parse(JSON.stringify({ ...obj1, ...obj2 })));
复制代码

递归调用实现

image

9、类操做

在以前定义类是经过构造函数来操做的,es6新增了class关键字,此时,咱们也能够像其它语言同样来建立各类类了。

class Person{
  constructor(name, age){
      this.name = name;
      this.age = age;
  }
 
  print(){
    console.log('我叫' + this.name + ',今年' + this.age + '岁');
  }
}
复制代码

类的继承

小案例:五彩小球

运行效果:

image

核心代码:

image
image

10、集合操做

1.set

一个Set是一堆东西的集合,Set有点像数组,不过跟数组不同的是,Set里面不能有重复的内容;

// 建立一个集合
let set = new Set(['张三', '李四', '王五', '张三', '李四']);
console.log(set);
  
// 一个属性
console.log(set.size);
  
// 四个方法
// add
console.log(set.add('刘德华').add('旋之华'));
console.log(set);
  
// delete
console.log(set.delete('张三'));
console.log(set.delete('李四'));
console.log(set);
  
// has
console.log(set.has('张三'));
console.log(set.has('张三1'));
  
// clear
console.log(set.clear()); // undefined
console.log(set);
复制代码

2)map

Map结构提供了“值—值”的对应,是一种更完善的Hash结构实现。

若是你须要“键值对”的数据结构,Map比Object更合适。

它相似于对象,也是键值对的集合,可是“键”的范围不限于字符串,各类类型的值(包括对象)均可以看成键。

实例属性和方法:size、set、get、has、delete、clear

// 建立一个Map
  let obj1 = {a: 1}, obj2 = {b: 2};
  const map = new Map([
     ['name', '张三'],
     ['age', 18],
     ['sex', '男'],
     [obj1, '今每天气很好'],
     [obj2, '适合敲代码'],
     [[1,2], 'hhh']
  ]);
  
  console.log(map);
  console.log(map.size);
  // set和get
  map.set('friends', ['赵六', '力气']).set(['dog'], '小花');
  console.log(map);
  console.log(map.get('name'));
  console.log(map.get(obj1));
  
  // delete
  map.delete(obj1);
  console.log(map.delete('xxxx'));
  console.log(map);
  
  // has
  console.log(map.has(obj1));
  console.log(map.has(obj2));
  
  // clear
  map.clear();
  console.log(map);
  
  // 遍历
  map.forEach(function (value, index) {
     console.log(index + ':' + value);
  });
  
  // 注意事项
  map.set({}, '呵呵呵呵呵');
  map.set({}, '哈哈哈哈');
  
  console.log(map);
  console.log({} === {});
复制代码

11、Generator

为何要使用generator?

开发中, 好比在作网络请求时咱们会进行异步调用,为了保证调用顺序的正确性,一般咱们会用回调函数,也能够采用Promise相关的技术来操做。

还有一种经常使用的解决方案,它就是Generator生成器函数。

顾名思义,它是一个生成器,它也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器Iterator对象,咱们能够经过这个迭代器,手动地遍历相关的值、状态,保证正确的执行顺序。

1)声明

Generator的声明方式相似通常的函数声明,只是多了个*号,而且通常能够在函数内看到yield关键字。

function* showNames() {
      yield '张三';
      yield '李四';
      return '王五';
  }
  
  let show = showNames();
   // {done: false, value: "张三"}
  
  console.log(show.next());
  // {done: false, value: "李四"}
  
  console.log(show.next()); 
  // {done: true, value: "王五"}
  
  console.log(show.next()); 
  // {done: true, value: undefined}
  
  console.log(show.next());
复制代码

迭代器有一个next方法,每次执行的时候会返回一个对象,对象里面有两个属性,一个是value表示返回的值,还有就是布尔值done,表示是否迭代完成。

2)模拟实现

image

12、Proxy&&Reflect (了解)

从语法角度讲JavaScript不支持重载。

缘由很简单,JS中函数能够传入任意类型、任意个数的参数, 统统能够经过在函数内使用this.arguments得到。

这样,就没法实现同名函数参数列表不一样实现不一样功能。

固然,在实际使用过程当中,能够人为去检测传入实参的个数及类型,来进行不一样操做。 可是,这不能叫作重载。

ES6带来了Proxy和Reflect,配合使用能够实现重载。

Proxy用于修改某些操做的默认行为,至关于对原始想进行的操做进行“包装”;

Reflect对象的方法与Proxy对象的方法一一对应,这使得Proxy对象能够方便的调用对应的Reflect方法完成默认行为。

set实现:

image

PS: 什么时重载?

简单说,就是函数或者方法有相同的名称,可是参数列表不相同的情形,这样的同名不一样参数的函数或者方法之间,互相称之为重载函数或者方法。

获取代码,有疑惑、答疑,加我微信yejh9522沟通交流便可;下篇更新预告: ES7/8新特性,Async和Promise

相关文章
相关标签/搜索