ES6+知识点总结

ES6+知识点总结


前言

本文主要介绍的是ES6以及更新的JavaScript脚本语言标准规范的使用。主要是对相关知识点的自我认知和理解,如有不对的地方,望指出并探讨

一、变量的声明

1.let关键字

通过let关键字声明变量

let dzw = "大张伟";

let关键字声明的变量的特点:

  • 没有声明提前(无建立阶段),不存在变量提升
  • 有区域性,形成块级作用域
  • 自动形成闭包
  • 同一个作用域内,不能定义重复变量
  • 不影响作用域链
  • 存在暂时性死区:不能在声明之前,使用该变量(使用let声明的变量名,在let声明之前的使用,都是暂时性死区)
  • 不会挂载到全局对象
  • 相对const而言,let可以不用必须赋初始值

var关键字声明的变量特点

  • 声明提前(有建立阶段),存在变量提升,(即是定义之前可以使用)
  • 没有区域性,无法形成块级作用域
  • 可以重估声明变量
  • window环境下,使用var,会将该变量挂载到window对象上

1.let经典应用理解

  • 循环中使用异步函数

var关键字

for (var i = 1; i <= 10; i++) {
    console.log(i, "outer"); // 1 - 10
    setTimeout(function () {
        console.log(i, "inner"); // 10 个 11
    }, i * 500);
}

分析:

var i = 1,首先是不会形成局部作用域的,而且会将i变量的声明提升至for循环体的外面,这里会挂载到window对象下,同步逻辑代码for循环执行完后 ,再执行 setTimeout异步代码,此时在setTimeout异步里面,存在变量i,但没有声明,所以会向父级作用域链查找,找到了window.i = 10++; 所以会打印10个11

使用IIFE,立即执行函数解决这个问题

for (var i = 1; i <= 10; i++) {
    setTimeout((function (j) {
        return function() {
            console.log(j);
        }
    })(i), i * 500);
}

分析:

这里会把每次循环的变量i,传到setTimeout的回调函数里,使用闭包的方式,进行变量的保存,当然会存在闭包的缺点,比如变量无法销毁,导致内存的泄露

使用let关键字解决这个问题

for (let i = 1; i <= 10; i++) {
    console.log(i, "outer"); // 1 - 10
    setTimeout(function () {
        console.log(i, "inner"); // 1-10
    }, i * 500);
}

分析:

let i = 1; 不存在变量声明提升,而且会形成局部作用域{},将当前循环的变量保存到当前的作用域下;每次迭代都形成一个具有新的初始化let i的局部作用域,且每个let i 互不影响。之后的每一个初始化的i值,都是上一次迭代的i的结果,因此在同步for代码执行完后,再执行setTimeout,会在当前局部作用域下,找到之前保存的初始化的i变量值。 因为变量i的持久保存(遇到每个作用域的 } ,let销毁,作用域销毁),所以let会自动形成闭包

二、常量的声明

1.const关键字

通过const关键字声明常量

const DZW = "大张伟";

const定义的常量的特点:

  • 有区域性,会形成局部作用域/ 块级作用于
  • 常量的栈值不能修改 【只能锁住基本数据类型】
  • 无建立阶段,(不存在声明提前)
  • 必须赋初始值,(与let的不同)
  • 锁栈不锁堆,(基本类型不能更改,但是引用类型的属性还是可以更改的`
  • 常量名一般的 需要全部大写

锁栈不锁堆的扩展:

使用Object.freeze(obj); 可以锁住对象(锁堆)

const DZW = {
	age : 18
};
Object.freeze(DZW);
DZW.age = 35;  // DZW 这个对象被冻结,其内部属性更改失败
console.log(DAW.age) // 18

三、扩展运算符:…

… 扩展运算符将数组转化为 逗号分隔的实参参数序列: test(…arr)

应用一:使用扩展运算符实现数组的合并

let xing = ["大"];
let ming = ["张伟"];
let dzw = [...xing, ...ming]; // ["大","张伟"]

应用二:数组克隆: 浅拷贝

let dzw = ["大","张伟"]; 
let _dzw = [...dzw];
console.log(_dzw);

应用三:类数组转数组

function add() {
    // 类数组 Array.isArray(arguments)
    console.log(arguments, Array.isArray(arguments)); // [Arguments] { '0': 1, '1': 2, '2': 3 } false
    let _argu = [...arguments];
    console.log(_argu, Array.isArray(_argu));  // [ 1, 2, 3 ] true
}
add(1, 2, 3);

应用三:求数组中的最大值

var arr = [1,3,5,7,2,9,8];
// var max = Math.max(1, 3, 5, 7, 2, 9, 8);
// var max = Math.max.apply(Math,arr);   //apply所接收的参数是一个数组
var max = Math.max(...arr);

四、解构赋值

1、数组的解构赋值

let arr = ['篮球', 'music'];
let [ball, other] = arr; // ball = '篮球' other = 'music'

2、对象的解构赋值

let zhw = {
	name: 'zhw'
	age: 18,
	say(){
	 console.log('hello')
	}
}
let { say } = zhw;
say()  // 'hello’

五、模板字符串

模板字符串使用 `` 反引号

特性:

  • 字符串内容可以直接换行
  • 可以使用${}拼接变量

六、箭头函数

const test = (a, b) => {
	return a + b
}
const sum = test(1, 2)
console.log(sum) // 3

特性:

  • this是静态的。 this始终指向函数声明时, 所在作用域下的this。即箭头函数的this指向箭头函数的外层。静态的是指: call、apply、bind不能改变箭头函数的this指向
  • 不能作为构造函数实例化对象【无构造器】
  • 不能使用保存实参的 arguments 变量
  • 简写:形参有且只有一个,省略形参的() ; 代码体只有一条语句,省略代码体的{} 和return 关键字

使用场景:箭头函数适合与this无关的回调,比如

  • 定时器
  • 数组的方法回调

不适用场景:箭头函数不适合与this有关的回调,比如

  • DOM等事件回调 【dom事件如果使用箭头函数,那么this指向的不再是DOM事件源】
  • 对象的方法

七、rest参数【ES6只针对数组,ES9中rest和…可以处理对象了】

ES6引入rest参数, 用于获取函数的实参,用来代替 arguments

1. es5中收集实参

function test() {
	// arguments收集到的实参是一个包裹了1, 2, 3, 4, 5的类数组,本质是一个对象
	console.log(arguments)
}
test(1, 2, 3, 4, 5)

可以通过以下方法将类数组arguments 转化为数组

  • const array = Array.from(arguments);
  • const array = Array.prototype.slice.call(arguments)
  • const array = […arguments];

2. es6中收集实参

function test(...args) {
	// 收集的实参args是一个数组
	console.log(args);
}

注意:rest参数必须放在所有形参的最后, 否则会报语法错误

function test(a, b, ...args) {
	console.log(a);  // 1
	console.log(b);  // 2
	// 收集的实参args是一个数组
	console.log(args);  // [3, 4, 5]
}
test(1, 2, 3, 4, 5)

3、ES9:rest参数和…针对对象

function test(a, b, {...args}) {
    console.log(a);  // 1
    console.log(b);  // 2
    // 收集的实参args是一个数组
    console.log(args);  // [3, 4, 5]
}
test(1, 2, {name: 'zhw'})

八、Symbol

一种新的基本数据类型

1. 特点

  • Symbol的值是唯一的,且不可见。
  • Symbol的值不能与其他数据进行运算
  • Symbol定义的对象属性不能使用for…in,但可以使用Reflect.ownKeys获取所有键名

2. symbol类型的数据创建

let s = Symbol();
// let s2 = Symbol('当前symbol的描述信息')
let s2 = Symbol('desc')
let s3 = Symbol('desc')
console.log(s2 === s3) // false

// 对象方法创建symbol类型
let s4 = Symbol.for('desc')
let s5 = Symbol.for('desc')
console.log(s4 === s5) // true

3. symbol类型数据的作用:

用来解决命名冲突的问题,

4. 应用

给对象添加属性和方法, 避免别人覆盖属性

痛点:

// 假设这是别人写的对象, 我们并不知道对象里具体有哪些属性
let zhw = {
	name: '呵呵'
}

// 需要给对象zhw添加name属性
zhw.name = xxx   // 这样给对象添加属性是不安全的

解决: 使用Symbol()定义需要添加的属性

let needAddProps = {
	name: Symbol()
}

// 这样使用不会破坏原对象的数据结构
zhw[needAddProps.name] = xxx

其他方法向对象添加Symbol类型的属性

let zhw = {
	name: '呵呵',
	[Symbol('say')]: function() {
		console.log('hello')
	}
}

5. Symbol的内置属性

Symbol有自己的一些内置属性, 这些属性都是用来控制 对象在特定情况下的表现, 例如

Sysbol.isConcatSpreadable 控制数组是否可以展开

let arr = [1, 2, 3]
let arr2 = [4, 5, 6]
console.log(arr.concat(arr2)) // [1, 2, 3, 4, 5, 6]

// 禁止arr2数组展开
arr2[Sysbol.isConcatSpreadable] = false
console.log(arr.concat(arr2)) // [1, 2, 3, [4, 5, 6]]

6、description: 获取Symbol的描述信息

let s = Symbol('zhw')
console.log(s.description);

九、迭代器

迭代器(Iterator)是一种接口,为不同的数据结构提供统一的访问机制。
js中,迭代器的本质是 对象属性

1、原生js具备Iterator接口的数据

  • Array
  • Arguments
  • Set
  • Map
  • String
  • TypedArray
  • NodeList

注意:只要部署了Iterator接口,就可以使用ES6提供的for…of命令遍历

2、迭代器的工作原理

  • 创建了一个指针对象iterator,指向了数据结构的起始位置 【let iterator = objSymbol.iterator
  • 第一次调用对象的next方法,指针自动指向数据结构的第一个成员 【iterator.next()】
  • 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
  • 每次调用next方法,都会返回一个包含value和done属性的对象

3、迭代器的应用:自定义遍历数据

let zhw = {
	name: '呵呵'
	hobbies: [
		'篮球',
		'rap'
	]
}
// 报错: zhw对象无iterator
for(let item of zhw) {
}

给对象加入迭代器

let zhw = {
	name: '呵呵'
	hobbies: [
		'篮球',
		'rap'
	],
	[Symbol.iterator]() {
		let index = 0
		// 返回一个指针对象
		return {
			next: () => {
				if(index < this.hobbies.length) {
					const result = {value: this.hobbies[index], done: false)
					index++
					return result
				} else {
					return {value: undefined, done: true}
				}
			}
		}
	}
}

十、生成器: ES6的异步编程解决方案1

生成器本质是一个函数。 生成器的返回结果其实是一个迭代器对象,因为具有next方法

1、作用

  • 一种异步编程的解决方法: 解决原生js的纯回调函数,造成的回调地狱问题

2、语法

  • 迭代器函数的声明
// * 位置可左可右可中间
function * gen() {
	console.log('hello')
}
  • 迭代器函数的调用
let iterator = gen();
// 迭代器函数的调用语句,执行生成器函数体的语句
iterator.next()  // 返回结果是yield对应的值

3、yield 生成器函数代码体的分隔符

n个yield,将代码体分割成n + 1块

function * gen() {
    console.log(111)
    yield '分隔符1';
    console.log(222)
    yield '分隔符2';
    console.log(333)
    yield '分隔符3';
    console.log(444)
}
for (const iterator of gen()) {
    console.log(iterator);
    console.log('======')
}

在这里插入图片描述

4、生成器函数的参数

  • 生成器函数的参数
function * gen(arg) {
    console.log(arg)
}
let iterator = gen('生成器函数的参数')
iterator.next()  // 执行了 console.log(arg)
  • 生成器返回的迭代器对象的next方法参数

第n个yield的返回值,保存着第n + 1个的next方法参数

function * gen() {
   console.log('代码块1')
   let one = yield 111;
   console.log(one, 'zhw');
   console.log('代码块2')
}
let iterator = gen()
iterator.next()
iterator.next('第2个next的参数')

next传多个参数 用数组: Generator<number, void, unknown>.next(…args: [] | [unknown]): IteratorResult<number, void>

function * gen() {
   console.log('代码块1')
   let one = yield 111;
   console.log(one);
   console.log('代码块2')
}
let iterator = gen()
iterator.next()
iterator.next(['第2个next的参数', 'zhw'])

在这里插入图片描述

5、生成器函数的应用:

例如: 1s后打印111,2秒后打印222, 3秒后打印333

  • 原生js的实现
 setTimeout(function(){
   console.log(111)
    setTimeout(function(){
        console.log(222)
        setTimeout(function(){
            console.log(333)
        }, 3000)
    }, 2000)
}, 1000)

缺点:多层回调嵌套造成了 地狱回调【一种回调现象】,不便于阅读和维护代码

  • 生成器解决回调地狱问题
function one(timer, num) {
  setTimeout(() => {
    console.log(num);
    // 第二次调用next  可以通过第一个yield获取参数数据
    iterator.next('one')
  }, timer);
}
function two(timer, num) {
  setTimeout(() => {
    console.log(num);
    // 第三次next  此时会调用: yield three(3000, 333)
    // 不过第三次的next参数 是传递给第二个yield的返回值的
    iterator.next('two')
  }, timer);
}
function three(timer, num) {
  setTimeout(() => {
    console.log(num);
    iterator.next('three')
  }, timer);
}

function * gen() {
  let resOne = yield one(1000, 111);
  console.log(resOne);
  let resTwo = yield two(2000, 222);
  // 第三次yield的参数
  console.log(resTwo);
  const resThree = yield three(3000, 333);
  console.log(resThree);
}

let iterator = gen()
// 第一次调用next
iterator.next()

十一、Promise: ES6的异步编程解决方案2

Promise本质是一个构造函数。 是ES6引入的异步编程的一种解决方案,主要是用来解决原生js造成的回调地狱现象

1、基本语法

let p = new Promise((resolve, reject) => {
   setTimeout(() => {
        resolve('111')
        // reject('err')
    }, 500)
})
p.then((res)=>{
    console.log(res); // 111
}, (err)=>{
    console.log(err); // err
})
p,catch(err=>{
	console.log(err); // err
})

p.then(成功的回到, 失败的回调)

2、关于then的返回值

p.then()的返回值始终是一个Promise。具体状态(PromiseState),由回调参数的返回值决定,规则如下

  • 1、没有return(即是返回undefined) / 返回非Promise的值 状态为:fulfilled
  • 2、return返回Promise对象: 状态和返回的Promise状态保持一致
let p = new Promise((resolve, reject) => {
   setTimeout(() => {
        // resolve('111')
        reject('err')
    }, 500)
})
// p.then()的返回值始终是一个Promise。具体状态(PromiseState),由回调参数的返回值决定,规则如下
// 1、没有return(即是返回undefined) / 返回非Promise的值  状态为:fulfilled
// 2、return返回Promise对象: 状态和返回的Promise状态保持一致
let res = p.then((res)=>{
    console.log(res); // 111
    // resolve('111') 触发return
}, (err)=>{
    console.log(err); // err
    // reject('err') 触发return
    return new Promise((resolve, reject) => {
        resolve('res')
    })
})
console.log(res, 'res'); // PromiseState: fulfilled, PromiseResult: 'eee'

3、解决异步回调

需求: 1s后打印111,2秒后打印222, 3秒后打印333

  • 通过then方法的链式语法
let p = new Promise((resolve, reject) => {
   setTimeout(() => {
       resolve(111);
   }, 1000)
})
p.then((res)=>{  // 这个res是p对象的Promise的执行结果
   console.log(res);
   return new Promise((resolve, reject) => {
       setTimeout(()=>{
           resolve(222)
       }, 2000)
   })
}).then(res=>{  // 这个res是上一个回调参数的 promise执行结果
   console.log(res);
   return new Promise((resolve, reject) => {
       setTimeout(()=>{
           resolve(333)
       }, 3000)
   })
}).then(res => { // 这个res是上一个回调参数的 promise执行结果
   console.log(res);
})

4、处理Promise对象数组

  • Promise.allSettled: 每个Promise都能得到结果时
const p1 = new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve('111')
   }, 1000)
 })

 const p2 = new Promise((resolve, reject) => {
   setTimeout(() => {
     reject('222')
   }, 2000)
 })
 // PromiseState: 始终是fulfilled
 // PromiseResult[]: 
 // [{status: 'fulfilled', reason: '111'} , {status: 'rejected', reason: '111'}]
 const res = Promise.allSettled([p1, p2])
 console.log(res);
  • Promise.all: 每个Promise都能得到resolve结果时, 如果一个是resolve,另一个是reject,则是在pending中;如果两个都是reject,则结果状态时rejected,值是第一个Promise元素的值
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('111')
  }, 1000)    
}) 

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('222')
  }, 2000)    
})    
// PromiseState: fulfilled
// PromiseResult[]: 
// ['111', '222']
const res = Promise.all([p1, p2])
console.log(res);  

ES8之async和 await: 【第三种异步解决方案】

async 和 await 结合可以让异步代码 像同步一样执行

1、async函数

  • async函数的返回值为promise对象, 返回值promise的具体状态,如下:
async function fn() {
    // 1. 返回 非 Promise对象时, fn()的返回状态为: fulfilled
    // return 'zhw'
    
    // 2. 抛出一个错误时, fn()的返回状态为: rejected
    // throw new Error('error')

    // 3. 返回一个Promise对象时, fn()的返回状态 由 return 的 Promise状态决定
    return new Promise((resolve, reject) => {
        // resolve('data')
        reject('error')
    })
}
// res为一个Promise对象, 所以可以使用then()
let res = fn()
console.log(res);
  • async函数可以没有await 表达式

2、await 表达式

  • await 必须写在async函数中
  • await 右侧的表达式一般为 promise对象
  • await始终返回promise成功的值
  • await的promise失败了, 需要使用try…catch 捕获处理异常

3、第三种异步解决案例,【async + await】

1s后打印111,2秒后打印222, 3秒后打印333

function one() {
   return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(111);
        }, 1000)
    })
}
function two() {
   return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(222);
        }, 2000)
    })
}
function three() {
   return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(333);
        }, 3000)
    })
}

async function test() {
   let _one = await one();
   console.log(_one)
   let _two = await two();
   console.log(_two)
   let _three = await three();
   console.log(_three)
}
test()

十二、Set集合

集合:ES6提供的一种数据集合。类似于数组,但不是数组。本质是一个对象【typeof new Set === ‘object’】。成员都是唯一的。Set实现了迭代器接口,所以可以使用扩展运算符…和for…of

1、Set集合对象的属性和方法

  • size: 集合元素的个数
  • add() 增加一个新元素,返回当前集合
  • delete() 删除元素 返回boolean值
  • has() 检测集合中是否包含某个元素, 返回boolean
  • clear() 清空当前集合对象
let arr = [1, 2, 3, 4, 2, 1]
let s = new Set(arr)
console.log(typeof s);  // 'object'
console.log(s.size);  // Set对象个数
// let s2 = s.add(5)
// console.log(s === s2);  // true: Set(5) {1, 2, 3, 4, 5}
// let flag = s.delete(1)
// console.log(s); // Set(5) {2, 3, 4}

console.log(s.has(1));
s.clear()
console.log(s);


let arr = [1, 2, 3, 4, 2, 1]
let s = new Set(arr)
for (const item of s) {
    console.log(item);  // 1, 2, 3, 4
}

2、Set集合的应用

  • 数组去重
let arr = [1, 2, 3, 4, 2, 1]
let s = new Set(arr)  // 类数组 Set自带去重
let sArr = [...s]  // 类数组转数组
console.log(sArr);

十三、Map

ES6提供的新的数据结构。Map数据结构是一种用于存储键值对的数据结构,是一种升级版的对象,即对象的key不限于字符串,key可以是各种类型,Map中的键是唯一的。实现了迭代器接口,可以用扩展运算符…和for…of进行遍历

1、Map的属性和方法

  • size: 返回Map的元素个数
  • set: 新增一个新的元素,放回当前Map
  • get: 根据键名获取键值
  • has: 检测Map是否包含某个元素
  • clear: 清空集合, 返回undefined
let obj = {name: 'zhw'}
let m = new Map()
m.set('name', 'zhw')
m.set('age', 18) // 被覆盖
m.set('age', 22) // Map的键是唯一的  下面会覆盖上面的
m.set('say', () => {console.log('i say');})
m.set(obj, 'zhw?')
// console.log(m); // 0: {"name" => "zhw"}
// for (const item of m) {
//     //  每一项是一个数组[key, value] 
//     console.log(item);  // ['name', 'zhw']
// }

let arr = [...m]
console.log(arr); // [Array(2), Array(2), Array(2)]   ['name', 'zhw']

console.log(m.get('name'));
console.log(m.get(obj));
console.log(m.has('age'))
// m.clear()
console.log(m.clear()) // undefined

2、Map转对象

//  二维数组 转对象
const result = Object.fromEntries([
  ['name', 'zhw'],
  ['age', 18]
 ])
 console.log(result);

const m = new Map()
m.set('name', 'zhw')
// Map就是一个二维数组 
const result2 = Object.fromEntries(m)
console.log(result2);

十四、class类

这里的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法

1、实例化一个基本对象

  • 原生js
function Person(name, age) {
   // new Person() 就会执行这里的代码体
    this.name = name || 'zhw';
    this.age = age;
    // console.log(this);
}
Person.prototype.say = function() {
    console.log('i say');
}
// 构造函数的静态属性
Person.p = 'Peron对象上的属性p'  // Peron对象上的属性:会挂载到实例化对象的原型上
Person.prototype.test = 'Person原型上的属性test' // Person原型上的属性, 会呗实例化对象直接访问到
let zhw = new Person('zhw', 22)
// zhw.__proto__.constructor === Person 
// console.log(zhw.__proto__.constructor === Person);  // true
console.log(zhw.test);
console.log(zhw.__proto__ === Person.prototype); // true
  • class类
class Person {
   constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 类似原生的Person.p
    // 静态属性属于类/或者构造函数, 不属于实例对象
    static p = 'Peron对象上的静态属性p'
    // 类的非静态属性
    test = 'Person原型上的属性test'  // 和构造方法里面的属性同级
    // Person.prototype.say的简化
    // 这块必须是ES6的简介方法,不能出现function关键字的完整写法
    say() {
        console.log('i say'); 
    }
    
}

let zhw = new Person('zhw', 19)
// zhw.say()
// console.log(zhw, 'zhw');
// 访问类的静态属性
// console.log(zhw.__proto__.constructor === Person); // true
// console.log(Person.p);

console.log(zhw.test);

2、关于继承

ES5原生 构造函数实现继承

 // 父构造方法
 // 手机
 function Phone(color, price) {
     this.color = color;
     this.price = price;
 }
 Phone.prototype.call = function() {
     console.log('打电话');
 }

 // 子构造方法
 // 智能手机
 function SmartPhone(color, price, size) {
     // this指向SmartPhone
     Phone.call(this, color, price);  // 类似super()
     this.size = size
 }

 // 设置子构造函数的原型

 // SmartPhone的原型指向了父构造函数  无参构造实例对象
 SmartPhone.prototype = new Phone();
 // 还原SmartPhone的构造函数指向
 SmartPhone.prototype.constructor = SmartPhone;
 
 // 声明子构造函数的方法
 SmartPhone.prototype.playGame = function() {
     console.log('玩游戏');
 }

 const HuaWei = new SmartPhone('黑色', 3999, '15px')
 console.log(HuaWei, 'xx');

ES6 class类实现继承

// 父类
// 手机
class Phone {
    constructor(color, price) {
        this.color = color;
        this.price = price;
    }
    call() {
        console.log('打电话');
    }
}

// 子类智能手机
class SmartPhone extends Phone{
    constructor(color, price,size) {
        // 调用父类的构造函数
        super(color, price);
        this.size = size;
    }
    playGame() {
        console.log('打游戏');
    }
}

let huaWei = new SmartPhone('黑色', 1000, '大得很');
console.log(huaWei);

3、私有属性

class Person {
	// 公有属性
	name;
	// 私有属性
	#sex;
	constructor(name, sex) {
		this.name = name;
		this.#sex = sex;
	}
	// 只有在类里面才可以访问私有属性
}

十五、数值的扩展

  • Number.SPSILON: 表示最小精度
  • Number.isFinite : 是否为有限数
  • Number.isNaN: 是否为NaN
  • Number.parseInt : 字符串转整数
  • Number.isInteger: 是否为整数
  • Math.trunc: 将数字的小数部分去掉
  • Math.sign 是否为正数、负数、还是零

十六、对象的扩展

  • Object.is() : Object.is(NaN,NaN) = true
  • Object.assign() 合并对象
  • Object.entries({}) 对象转二维数组
  • Object.fromEntries([[]]) 二维数组/Map 转 对象

1、ES8对象方法的扩展

  • Object.values() 返回可以枚举属性的属性值数组
  • Object.entries() 返回可遍历属性的 [key, valuie] 的数组, 【用于转Map对象】
  • Object.getOwnPropertyDescriptors(): 返回指定对象所有属性的描述对象【描述对象指:是否可枚举;是否可更改等】
const zhw = {
    name: 'zhw',
    age: 18,
    hobbies: ['篮球', 'rap'],
    other: {
        desc: '待定'
    },
}
// 获取对象所有的key
// console.log(Object.keys(zhw)); //  ['name', 'age', 'hobbies', 'other']
// 获取对象所有的值
// console.log(Object.values(zhw)); // ['zhw', 18, ['篮球', 'rap'], {desc: '待定'}]
// 将对象的键值用二维数组包裹起来
// [
//     ['name', 'zhw']
// ]

// 将对象转Map数据结构
// let m = new Map(Object.entries(zhw))
// console.log(m.get('name'));

// Object.getOwnPropertyDescriptors(): 获取对象属性的描述对象

// 自定义创建对象
// zhw将挂载在other_zhw的原型上
const other_zhw = Object.create(zhw, {
    // 属性名: 描述对象
    errorDesc: {
        value: "另一个我。 错了",
        writable: true,
        configurable: true,
        enumerable: true
    }
})
// 不会获取原型上zhw对象的属性描述对象
// 仅仅打印errorDesc属性的描述对象
console.log(Object.getOwnPropertyDescriptors(other_zhw))

数组的扩展

1、数组的扁平化

  • arr.flat()
// 将n维数组  转化为 n - 1维数组
// const arr = [1, 2, 3, [4, 5]]
 // console.log(arr.flat());  // [1, 2, 3, 4, 5]

 // const arr = [1, 2, 3, [4, 5, [6, 7]]]
 // console.log(arr.flat()); // [1, 2, 3, 4, 5, [6, 7]]

 const arr = [1, 2, 3, [4, 5, [6, 7]]]
 // 参数: 扁平化的深度  默认是1
 console.log(arr.flat(2)); //  [1, 2, 3, 4, 5, 6, 7]
  • arr.flatMap()
// 需求:一维数组的每个元素 * 10
const arr = [1, 2, 3, 4]
 // 结果是二维是数组
 // const res = arr.map(item => [item * 10]) // [[10], [20], [30], [40]]

 // 此时需要使用flatMap
 const res = arr.flatMap(item => [item * 10]) // [10, 20, 30, 40]
 console.log(res);

十七、ES6模块化

模块化:是指将一个大的程序文件,拆分成许多个小的文件,然后将小文件组合起来

1、模块化的好处

  • 防止命名冲突
  • 代码复用
  • 高维护性

2、模块化规范的产品

  • CommonJS: NodeJS、Browserify
  • AMD: requireJS
  • CMD: seaJS
  • Import:ES6

3、ES6模块化的语法

导出语句

  • 第一种
export const a = 1;
export const b = {};
export const c = () => {}
  • 第二种
const a = 1;
const b = {};
const c = () => {}
export {
	a,
	b,
	c
}
  • 第三种:默认导出
export default {
	const a = 1;
	const b = {};
	const c = () => {}
}

导入语句

  • 三种导出方式,通用的导入语句
// m1 文件别名; as: 取别名关键字
import * as m1 from './src/js/m1.js
  • 第二种:解构赋值导入
import {a, b, c} from './src/js/m1.js'
// 当 当前文件import解构的变量重名时, 可以给重名的变量取别名
import {a as m2_a }  from './src/js/m2.js'
// 解构赋值的方法 导入默认导出的文件  也是默认导出文件的  
import {default as m3 } from './src/js/m3.js'
  • 第三种:默认导出的简便导入
// m3: 自定义的
import m3 from './src/js/m3.js'

十八、ES7的新特性

1、数组的includes()

判断数组中, 是否包含某个元素。替代原生的 indexOf

2、** 指数运算符

** 指数运算符 替代 原生的 Math.pow(2, 10)

console.log(2 ** 10)
console.log(Math.pow(2, 10))

十九、bigint大整形

又一个新的基本类型

let n = 521n;
console.log(n, typeof n); // 521n 'bigint'

1、BigInt函数

let n = 521;
console.log(BigInt(n)); // 521n 
// 参数只能是整数
console.log(BigInt(1.2)); // error

2、应用

  • 大数值运算
let max = Number.MAX_SAFE_INTEGER;
//  console.log(max); // 9007199254740991
//  console.log(max + 1); // 9007199254740992
//  // 再 + 1 大数值未变
//  console.log(max + 2); // 9007199254740992

// 希望大数值变化
console.log(BigInt(max)); // 9007199254740991n
console.log(BigInt(max) + BigInt(1)); // 9007199254740992n
// bigint 只能和bigint类型运算  
// 所以这里的2 也需要转换为bigint再运算
console.log(BigInt(max) + BigInt(2)); // 9007199254740993n
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原谅我很悲

不要打赏哦,加个好友一起学习呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值