ES6笔记

一、变量的声明
1.let关键字
通过let关键字声明变量

let dzw = “大张伟”;
1
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 = “大张伟”;
1
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];

  1. 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

  1. symbol类型数据的作用:
    用来解决命名冲突的问题,

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

痛点:

// 假设这是别人写的对象, 我们并不知道对象里具体有哪些属性
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’)
}
}

  1. 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’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值