重学前端-ES6+新特性总结

前言

最近开始重学前端,学习过程中将笔记跟大家分享,希望对大家有所帮助,共同成长,文章中有不对的地方请大家指正。

本文简单列举了ES6+中的一些新特性,部分知识点涉及面过大,本文将一带而过,后面将会另起一篇去做详细介绍,比如:Promise,Generator等。

正文

1. let、const块级作用域以及和var的区别

  • let、const声明的变量,在for,if语句中,会形成块级作用域,块级作用域内的变量,不能被作用域外部使用
  • let、const声明变量不再会有声明提升,在变量声明之前使用运行时会报错
//块级作用域一级块级作用域的使用 if(true) { const param = 'param in if block'; console.log(param);//param in if block } console.log(param);//块级作用域外访问内部定义的变量,ReferenceError: param is not defined
  • 块级作用域声明变量,会出现“暂时性死区”,块级作用域声明变量前使用变量,将会报错
// 暂时性死区 const i = 100; if(i) { console.log(i); //ReferenceError: Cannot access 'i' before initialization const i = 1000; }
  • const声明的是一个常量,声明必须初始化
// const常量声明必须初始化 const i; i = 10; console.log(i) //SyntaxError: Missing initializer in const declaration
  • 如果const声明的是基本类型常量,初始化之后不能修改;引用类型的常量,可以修改其成员变量;
// 基本类型常量不能修改,引用类型常量能修改属性 const str = 'str'; str = 'str1';//TypeError: Assignment to constant variable. const arr = [1, 2, 3]; arr[0] = 100; console.log(arr[0]) //100
  • 和var的区别
声明方式变量提升作用域初始值重复定义
var函数级不需要允许
let块级不需要不允许
const块级必需不允许

2.解构-快速提取数组/对象中的元素

  • 数组解构

  • 单独解构-根据数组索引,将数组解构成单独的元素

const arr = [1, 2, 3]; const [a, b, c] = arr; console.log(a, b, c);//1,2,3 const [, , d] = arr; console.log(d)//3
  • 默认值,解构时可以给变量设置默认值,数组没有这个元素的话
const arr = [1, 2, 3]; const [, , , defaultVal = '4'] = arr; console.log('设置默认值',defaultVal);
  • 剩余解构-用 "...+变量名" 解构剩余参数到新数组,只能用一次
const arr = [1, 2, 3]; const [e, ...rest] = arr; console.log(rest)//[2, 3]
  • 实例应用
// 拆分字符串 const str = 'xiaobai/18/200'; const strArr = str.split('/'); const [, age, ] = strArr; console.log(age)//18
  • 对象解构

  • 单个/多个解构-跟数组解构差不多

const obj = {name: 'xiaohui', age: 18, height: undefined}; const {name, age} = obj; console.log(name, age) // 'xiaohui', 18
  • 解构+重命名-给解构出来的变量重命名
const obj = {name: 'xiaohui', age: 18, height: undefined}; const {mame: objMame} = obj; console.log(objMame)
  • 默认值-给解构变量设置默认值
const obj = {name: 'xiaohui', age: 18, height: undefined}; const {mame: objMame} = obj; console.log(objMame)

3.模板字符串

  • 用法:

  • 使用``将字符串包裹起来

  • 功能:

  • 可以换行、插值、使用标签函数进行字符串操作

  • 示例:

  • 换行/插值

//换行 const str = `fdsjak fdsa` console.log(str) // 插值 const strs = `random: ${Math.random()}`; console.log(strs)
  • 标签函数-可以对模板字符串的字符串和插值进行处理和过滤等操作
/** * 字符串模板函数 * @param {array} strs 以插值为分隔符组成的字符串数组 * @param {string} name 插值的value,有多少个就会传入多少个 */ const tagFunc = (strs, name, gender) => { const [str1, str2, str3] = strs; const genderParsed = gender == "1" ? "男" : "女"; // 可以在此做过滤,字符串处理,多语言等操作 return str1 + name + str2 + str3 + genderParsed; }; // 带标签的模板字符串, const person = { name: "xiaohui", gender: 1, }; // 返回值为标签函数的返回值 const result = tagFunc`my name is ${person.name}.gender is ${person.gender}`; console.log(result);//my name is xiaohui.gender is 男

4. 字符串扩展方法

  • includes-是否包含
  • startsWith-是否以什么开始
  • endsWith-是否以什么结束
const str = 'abcd'; console.log(str.includes('e'));//false console.log(str.startsWith('a'));//true console.log(str.endsWith('a'))//false

5.参数默认值&剩余参数

  • 给函数形参设置默认值
// 带默认参数的形参一般放在后面,减少传参导致的错误几率 const defaultParams = function (name,age = 0) { return [age, name] }; console.log(defaultParams(1))
  • 使用...rest形式设置剩余形参,支持无限参数
// 剩余参数,转化成数组 const restParams = function(...args) { console.log(args.toString());//1, 2, 3, 4, 5 } restParams(1, 2, 3, 4, 5)

6.展开数组

使用...将数组展开

const arr = [1, 2, 3]; console.log(...arr); // 等价于es5中以下写法 console.log.apply(console, arr)

7.箭头函数

特性&优势:

  • 1、简化了函数的写法
  • 2、没有this机制,this继承自上一个函数的上下文,如果上一层没有函数,则指向window
  • 3、作为异步回调函数时,可解决this指向问题
const inc = n => n + 1; console.log(inc(100)) const obj = { name: 'aa', func() { setTimeout(() => { console.log(this.name);//aa }, 0); setTimeout(function() { console.log(this.name);//undefined }, 0); } } obj.func();

8.对象字面量增强

  • 同名属性可以省略key:value形式,直接key,
  • 函数可以省略key:value形式
  • 可以直接func(),
  • 可以使用计算属性,比如:{[Math.random()]: value}
/** * 1、增强了对象字面量: * 1,同名属性可以省略key:value形式,直接key, * 2,函数可以省略key:value形式 * 3,可以直接func(), * 4,可以使用计算属性,比如:{[Math.random()]: value} */ const arr = [1, 2, 3]; const obj = { arr, func(){console.log(this.arr)}, [Math.random()]: arr } console.log(obj)

9.Object.assign(target1, target2, targetN)-复制/合并对象

/** * Object.assign(target1, target2, ...targetn) * 后面的属性向前面的属性合并 * 如果target1是空对象,可以创建一个全新对象,而不是对象引用 */ const obj1 = { a: 1, b: 2 }; const obj2 = { a: 1, b: 2, }; const obj3 = Object.assign({}, obj1); obj3.a = 5; console.log(obj3, obj2, obj1);

10.Object.is(value1, value2)

作用:

比较两个值是否相等

特性:

  • 没有隐式转换
  • 可以比较+0,-0、NaN
console.log(NaN === NaN) //false console.log(Object.is(NaN, NaN)) //true console.log(0 === -0) // true console.log(Object.is(0, -0))//false console.log(Object.is(1, 1))//true

11.Proxy(object, handler)

作用:

  • 代理一个对象的所有,包括读写操作和各种操作的监听

用法:

const P = { n: "p", a: 19, }; const proxy = new Proxy(P, { get(target, property) { console.log(target, property); return property in target ? target[property] : null; }, defineProperty(target, property, attrs) { console.log(target, property, attrs); // throw new Error('不允许修改') }, deleteProperty(target, property) { console.log(target, property); delete target[property]; }, set(target, property, value) { target[property] = value; }, }); proxy.c = 100; console.log('pp',P);

与Object.definePropert对比

优势:
  • 拥有很多defineProperty没有的属性方法,比如:

  • handler.getPrototypeOf() ---Object.getPrototypeOf 方法的监听器
  • handler.setPrototypeOf() ---Object.setPrototypeOf 方法的监听器。
  • handler.isExtensible() ---Object.isExtensible 方法的监听器。
  • handler.preventExtensions() ---Object.preventExtensions 方法的监听器。
  • handler.getOwnPropertyDescriptor() ---Object.getOwnPropertyDescriptor 方法的监听器。
  • handler.defineProperty() ---Object.defineProperty 方法的监听器。
  • handler.has() ---in 操作符的监听器。
  • handler.get() ---属性读取操作的监听器。
  • handler.set() ---属性设置操作的监听器。
  • handler.deleteProperty() ---delete 操作符的监听器
  • handler.ownKeys() ---Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的监听器。
  • handler.apply() ---函数调用操作的监听器。
  • handler.construct() ---new 操作符的监听器。
  • 对数组的监视更方便

  • 以非侵入的访视监管对象的读写

12.Reflect

作用:

集成Object操作的所有方法,统一、方便,具体方法如下:

用于对对象的统一操作,集成Object相关的所有方法

1、apply:类似Function.prototype.apply

2、Reflect.construct()

对构造函数进行 new 操作,相当于执行 new target(...args)。

3、Reflect.defineProperty()

和 Object.defineProperty() 类似。

4、Reflect.deleteProperty()

作为函数的delete操作符,相当于执行 delete target[name]。

5、Reflect.get()

获取对象身上某个属性的值,类似于 target[name]。

6、Reflect.getOwnPropertyDescriptor()

类似于 Object.getOwnPropertyDescriptor()。

7、Reflect.getPrototypeOf()

类似于 Object.getPrototypeOf(), 获取目标对象的原型。

8、Reflect.has()

判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。

9、Reflect.isExtensible()

类似于 Object.isExtensible().判断对象是否可扩展,可以添加额外属性

Object.seal(封闭对象), Object.freeze(冻结对象)是不可扩展的

10、Reflect.ownKeys()

返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响).

11、Reflect.preventExtensions()

类似于 Object.preventExtensions()。返回一个Boolean。

12、Reflect.set()

将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true, 反之返回false。

13、Reflect.setPrototypeOf()

类似于 Object.setPrototypeOf()。

示例:

const obj = { name: 'reflect' } Reflect.preventExtensions(obj);//禁止扩展 console.log(Reflect.set(obj, 'age', 'xiaobai'))//false console.log(obj)//{ name: 'reflect' } console.log(Reflect.isExtensible(obj, 'name'))//false console.log(Reflect.ownKeys(obj))//[ 'name' ]

13.Promise

作用:解决异步编程中回调嵌套过深问题

14.class&静态方法&继承

  • 定义

  • 使用class关键字定义类

class Person{ constructor(props) { this.props = props; } }
  • 方法

  • 实例方法,需要实例化之后才能调用,this指向实例

  • 静态方法,用static修饰符修饰,可以直接通过类名调用,不需要实例化,this不指向实例,而是指向当前类
class Person{ constructor(props) { this.props = props; } // 实例方法 eat() { } // 静态方法 static run() { } } // 调用静态方法 Person.run(); const person = new Person('props'); // 调用实例方法 person.eat();
  • 继承:子类使用extends关键字实现继承,可以继承父类所有属性
class Student extends Person { constructor(props) { super(props); } printProps() { console.log(this.props); } } const student = new Student('student'); student.printProps();

15.Set

说明:

Set是一种类似于数组的数据结构

特性:

  • 元素唯一性,不允许重复元素
  • 使用add增加重复元素,将会被忽略

用途:

  • 数组去重
  • 数据存储
const arr = [1,3,1,1,1] const set = new Set(arr); set.add(1).add(1); console.log(set.size)//2 const newArr = Array.from(set); console.log(newArr)//[ 1, 3 ]

16.Map

说明:

类似Object,以key、value形式存储数据

区别:

Map键不会隐式转换成字符串,而是保持原有类型

实例:

const map = new Map(); map.set(1, 1); map.set('name', 'map') map.set(obj, obj) console.log(map.get(1)) //1 /** 1 1 name map { '1': 1, true: true, a: 'a' } { '1': 1, true: true, a: 'a' } */ map.forEach((val, key) => {console.log(key, val)})

17.Symbol

说明:

JavaScript第六种原始数据类型,用来定义一个唯一的变量

  • 作用:

  • 创建唯一的变量,解决对象键名重复问题

  • 为对象、类、函数等创建私有属性
  • 修改对象的toString标签

  • 为对象添加迭代器属性

  • 如何获取对象的symbol属性?

  • Object.getOwnPropertySymbols(object)

  • 实例
// 对象属性重名问题; const objSymbol = { [Symbol()]: 1, [Symbol()]: 2 } console.log(objSymbol) // 2、为对象、类、函数等创建私有属性 const name = Symbol(); const obj2 = { [name]: 'symbol', testPrivate() { console.log(this[name]); } } obj2.testPrivate(); // 定义toString标签; console.log(obj2.toString()); obj2[Symbol.toStringTag] = 'xx'; console.log(obj2.toString());//[object xx]

18.for...of...

用途:

已统一的方式,遍历所有引用数据类型

特性:

可以随时使用break终止遍历,而forEach不行

实例:

// 基本用法 // 遍历数组 const arr = [1, 2, 3, 4]; for(const item of arr) { if(item > 3) { break; } if(item > 2) { console.log(item) } } // 遍历set const set = new Set(); set.add('foo').add('bar'); for(const item of set) { console.log('set for of',item) } // 遍历map const map = new Map(); map.set('foo', 'one').set('bar', 'two'); for(const [key, val] of map) { console.log('for of map',key, val) } //迭代对象 const obj = { name: "xiaohui", age: "10", store: [1, 2, 3], // 实现可迭代的接口 [Symbol.iterator]: function () { const params = [this.name, this.age, this.store] let index = 0; return { next() { const ret = { value: params[index], done: index >= params.length, }; index++; return ret; }, }; }, }; for (const item of obj) { console.log("obj for of", item); }

19. 迭代器模式

/**
* 迭代器模式* 作用:通过Symbol.interator对外提供统一的接口,获取内部的数据
* 外部可以通过for...of...去迭代内部的数据*/
const tods = { life: ["eat", "sleep"], learn: ["js", "dart"], // 增加的任务 work: ["sale", "customer"], [Symbol.iterator]: function () { const all = []; Object.keys(this).forEach(key => { all.push(...this[key]) }) let index = 0; return { next() { const ret = { value: all[index], done: index >= all.length, }; index++; return ret; }, }; }, }; for (const item of tods) { console.log(item); }

20.Generator生成器

  • Generator
  • 函数前添加*,生成一个生成器
  • 一般配合yield关键字使用
  • 最大特点,惰性执行,调next才会往下执行
  • 主要用来解决异步回调过深的问题
// 生成迭代器方法 // 生成器Generator的应用 function* createIdGenerator() { let id = 1; while (id<3) yield id++; } const createId = createIdGenerator(); console.log(createId.next());//{ value: 1, done: false } console.log(createId.next());//{ value: 2, done: false } console.log(createId.next());//{ value: undefined, done: true } const todos = { life: ["eat", "sleep", "baba"], learn: ["es5", "es6", "design pattern"], work: ["b", "c", "framework"], [Symbol.iterator]: function* () { const all = [...this.life, ...this.learn, ...this.work]; for(const i of all) { yield i; } }, }; for(const item of todos) { console.log(item) }

21.includes函数-es2016

判断数组是否包含某个元素,包含NaN,解决indexOf无法查找NaN问题

// includes函数 const arr = ["foo", "bar", "baz", NaN]; console.log(arr.includes(NaN));//true console.log(arr.indexOf(NaN));//-1

22.** 运算符-es2016

指数运算

// 指数运算符 ** // es5中2十次方 console.log(Math.pow(2, 10)); // es6中2十次方 console.log(2 ** 10);

23.values函数-es2017

将对象的值以数组的形式返回

const obj = { foo: 1, bar: 2, baz: 3, }; console.log(Object.values(obj));//[ 1, 2, 3 ]

24.entries函数-es2017

将对象以键值对二维数组返回,使之可以使用for...of...遍历

const obj = { foo: 1, bar: 2, baz: 3, }; console.log(Object.entries(obj)); const entry = Object.entries(obj); for (const [key, value] of entry) { console.log(key, value); }

25.Object.getOwnPropertyDescriptors(obj)-es2017

获取对象的描述信息

可以通过获得的描述信息,配合Object.defineProperties来完整复制对象,包含get,set方法

// getOwnPropertyDescriptors // 普通get方法 const objGet = { foo: 1, bar: 2, get getCount() { return this.foo + this.bar; }, }; // assign方法会把getCount当做普通属性复制,从而getCount为3,修改bar不管用 const objGet1 = Object.assign({}, objGet); objGet1.bar = 3; console.log(objGet1.getCount);//3 // descriptors const descriptors = Object.getOwnPropertyDescriptors(objGet); console.log("des", descriptors); // 通过descriptors来复制对象,可以完整复制对象,包含get,set const objGet2 = Object.defineProperties({}, descriptors); objGet2.bar = 3; console.log(objGet2.getCount);//4

26.padStart, padEnd函数-es2017

在字符串前,或者后面追加指定字符串

参数:

targetLenght: 填充后的目标长度

padString:填充的字符串

规则:

1、填充的字符串超过目标长度,会在规定长度时被截断

2、填充字符串太短会以空格填充

3、padString未传值,以空格填充

作用:

一般用来对齐字符串输出

/** * foo.................|1 barbar..............|2 bazbazbaz...........|3 */ console.log(`${key.padEnd(20, '.')}${value.toString().padStart(2, '|')}`)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值