一 ECMAScript介绍

ECMAScript只提供了最基本的语法,JavaScript实现了ECMAScript的标准,是ECMAScript的扩展语言。在浏览器环境下,JavaScript就是ECMAScript加上web api(dom、bom);在node环境JavaScript就是ECMAScript加上node apis(fs、net等);JavaScript语言本身就是指ECMAScript;从ECMAScript2015开始,一年一迭代;
任何人都可以向标准委员会(又称 TC39 委员会)提案,要求修改语言标准。
一种新的语法从提案到变成正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准。

  • Stage 0 - Strawman(展示阶段)
  • Stage 1 - Proposal(征求意见阶段)
  • Stage 2 - Draft(草案阶段)
  • Stage 3 - Candidate(候选人阶段)
  • Stage 4 - Finished(定案阶段)

ES2015 及之后的版本也称ES6是相对于以前ES5的统称
ES6的入门看参考阮老师的博客https://es6.ruanyifeng.com/

二 常用的ES2015语法

1 块级作用域
let;先声明后引用,不会变量提示;for循环中的循环变量和循环体中变量可以同名,且互不影响;
2 const关键词
const声明时必须赋值;不改变内存地址;
3 数组解构

  1. const arr = [1,2,3,4,5];
  2. const a2 = [a,b,c,d,e=100,f = 'default'] = arr;
  3. const a3 = [a,...rest] = arr;
  4. console.log(a,b,c)
  5. console.log(e)
  6. console.log(f)
  7. console.log(rest)

4 对象解构

  1. const obj = {name: 'jason', age: 20};
  2. const {age} = obj;
  3. // 解构属性
  4. console.log(age);
  5. const name = 'tom';
  6. // 通过制定属性获取时,重复了,就用别名
  7. const {name: objName} = obj;
  8. // 默认值
  9. const {highSchool = 'NYPD'} = obj;
  10. console.log(highSchool);
  11. // 场景
  12. const {log} = console;
  13. log('11')

5 模板字符串-插值表达式

  1. const str = `Hello there, what,s up,
  2. there is a \`string\``;
  3. // 支持直接换行
  4. console.log(str)
  5. // 插值表达式
  6. const name = 'Lee';
  7. const msg = `hello, ${name}, are you ${20 * 1.5} yarns old? you got ${ Math.floor(Math.random() * 5)} children?`;
  8. console.log(msg)

6 模板字符串-模板函数

  1. // const str = console.log `Hello World`;
  2. const name = 'jason';
  3. const gender = true;
  4. function myTagFunc (string, name ,gender) {
  5. // console.log(string, name, gender)
  6. // return '123'
  7. const sex = gender?'man':'women';
  8. return string[0] + name + string[1] + sex + string[2]
  9. }
  10. const result = myTagFunc `Hey, ${name} is a ${gender}.`;
  11. console.log(result)

7 字符串的扩展方法
includes()、startsWith()、endsWith()、

  1. const msg = 'Error: foo is not defined';
  2. console.log(
  3. msg.startsWith('Error'),
  4. msg.endsWith('defined'),
  5. msg.includes('is not')
  6. )

8 参数默认值

  1. //判断默认值
  2. function foo(flag) {
  3. flag = flag === undefined ? true: false;
  4. console.log(flag)
  5. }
  6. // 给定默认值
  7. function foo(flag = true, ss) {
  8. console.log(flag, ss)
  9. }
  10. foo(undefined,1)

9 剩余参数

  1. function foo() {
  2. console.log(arguments)
  3. }
  4. // 只能放在形参的最后,且只能用一次
  5. function foo1(first,...rest) {
  6. console.log(rest)
  7. }
  8. foo(1,2,3,4,5)
  9. foo1(1,2,3,4,5)

10 数组展开

  1. const arr = ['jason', 'rich', 'jim'];
  2. // 参数确定
  3. console.log(
  4. arr[0],
  5. arr[1],
  6. arr[2],
  7. );
  8. // 参数不确定
  9. console.log.apply(console, arr);
  10. console.log(...arr)

11 箭头函数

  1. // function foo(n) {
  2. // return n * 1
  3. // }
  4. const foo = n => n * 1

12 箭头函数this指针 指向当前作用域

  1. const person = {
  2. name: 'Jason',
  3. say: function () {
  4. console.log(`hi, this is ${this.name}`)
  5. },
  6. sayArrow: () => {
  7. console.log(`hi, this is ${this.name}`)
  8. },
  9. sayAsync: function() {
  10. setTimeout(function() {
  11. console.log(this.name)
  12. }, 1000);
  13. },
  14. sayAsyncArrow: function() {
  15. setTimeout(() =>{
  16. console.log(this.name)
  17. }, 1000);
  18. }
  19. }
  20. person.say(); // hi, this is Jason
  21. person.sayArrow() // hi, this is undefined
  22. person.sayAsync() // undefined
  23. person.sayAsyncArrow() // Jason

13 对象字面量增强

  1. const bar = '123';
  2. const foo = {
  3. // bar: bar
  4. bar, // 省略同名属性
  5. // may: function() {
  6. // console.log('11')
  7. // }
  8. may() { // 省略冒号和function
  9. console.log('11');
  10. console.log(this)
  11. },
  12. [Math.random()]:'222' // 计算属性
  13. }
  14. foo.may()

14 对象扩展方法

  1. // Object.assign方法
  2. const source = {
  3. a:123,
  4. b:123
  5. }
  6. const target = {
  7. a: 456,
  8. c: 789
  9. }
  10. Object.assign(target, source);
  11. console.log(target) // { a: 123, c: 789, b: 123 }
  12. console.log(source) // { a: 123, b: 123 }
  13. // Object.is方法
  14. console.log(
  15. 0 == false,
  16. 0 === false,
  17. -0 === +0,
  18. Object.is(+0, -0),
  19. Object.is(NaN, NaN)
  20. )

15 代理proxy

  1. const person = {
  2. name:'Jason',
  3. age: 20
  4. }
  5. const personProxy = new Proxy(person, {
  6. get(target, prop) {
  7. console.log(target, prop);
  8. // return 100
  9. return prop in target ? target[prop]: 'has no prop'
  10. },
  11. set(target, prop, value) {
  12. console.log(target, prop, value);
  13. if(prop === 'age') {
  14. if(!Number.isInteger(value)) {
  15. throw new TypeError(`${value} is not int`)
  16. }
  17. }
  18. target[prop] = value;
  19. }
  20. });
  21. console.log(personProxy.name) // Jason
  22. console.log(personProxy.hight) // Jason
  23. // personProxy.age = '222'; // TypeError: 222 is not int
  24. personProxy.age = 22; // { name: 'Jason', age: 20 } age 22
  25. personProxy.height = '199cm'; // { name: 'Jason', age: 22 } height 199cm

16 proxy和defineProperty区别

  1. // object.defineProperty
  2. const man = {};
  3. Object.defineProperty(man, 'name', {
  4. get() {
  5. console.log('name visited')
  6. return man._name
  7. },
  8. set(value) {
  9. console.log('name setted')
  10. man._name = value;
  11. }
  12. })
  13. Object.defineProperty(man, 'age', {
  14. get() {
  15. console.log('age visited')
  16. return man._age
  17. },
  18. set(value) {
  19. console.log('age setted')
  20. man._age = value;
  21. }
  22. });
  23. man.name = 'jack';
  24. console.log(man.name);
  25. // name setted
  26. // name visited
  27. // jack
  28. // ----------------------------------proxy--------------------------
  29. // 对象的更多操作可以监视到
  30. // 更好的对数组对象的监视 之前想实现必须重写数组的方法
  31. // 非侵入的方式监视对象
  32. // delete也可以监视到
  33. const person = {
  34. name:'Jason',
  35. age: 20
  36. }
  37. const personProxy = new Proxy(person, {
  38. deleteProperty(target, prop) {
  39. console.log('delete ', prop)
  40. delete target[prop]
  41. }
  42. })
  43. delete personProxy.age;
  44. console.log(person) // { name: 'Jason' }
  45. // 对数组更好的监视
  46. const list = [];
  47. const listProxy = new Proxy(list, {
  48. set(target, prop, value) {
  49. console.log('set :', prop, value);
  50. target[prop] = value;
  51. return true; // 表示设置成功
  52. }
  53. })
  54. listProxy.push('sss') // set : 0 sss set : length 1

17 reflect对象,类似math对象,静态类不能通过new新建,内部封装了对对象底层的操作方法; reflect成员方法就是prox处理对象的默认实现

  1. const person = {
  2. name: 'Jason',
  3. age: 20
  4. }
  5. const personProxy = new Proxy(person, {
  6. get(target, prop) {
  7. console.log('watch prop get logic')
  8. return Reflect.get(target, prop)
  9. }
  10. });
  11. console.log(personProxy.age);
  12. // 提供了统一一套对对象的操作api 13个方法
  13. console.log('name' in person);
  14. console.log(delete person.name);
  15. console.log(Object.keys(person));
  16. console.log(Reflect.has(person, 'name'))
  17. console.log(Reflect.deleteProperty(person, 'name'))
  18. console.log(Reflect.ownKeys(person))

18 class相关

  1. // 以前
  2. // es6之前继承 参考博文地址 https://www.cnblogs.com/humin/p/4556820.html
  3. function Person(name, age) {
  4. this.name = name; // 通过this访问当前的实例对象
  5. this.age = age; // 通过this访问当前的实例对象
  6. // 实例方法
  7. this.hello = function() {
  8. console.log('hello there, my name is ' + this.name)
  9. }
  10. }
  11. // 原型方法
  12. // 如果要给当前所有的实例之间共享成员,需要借助成员的原型prototype
  13. Person.prototype.say = function() {
  14. console.log(`I am ${this.age} yarns old`)
  15. }
  16. // 继承
  17. // 1 将父类的实例作为子类的原型
  18. function Man (){};
  19. Man.prototype = new Person();
  20. Man.prototype.name = 'man';
  21. Man.prototype.age = 20;
  22. var man = new Man();
  23. console.log(man.name)
  24. console.log(man.say())
  25. console.log(man.hello())
  26. console.log('---------------');
  27. // 2 使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
  28. function Women(name, age) {
  29. Person.call(this);
  30. this.name = name||'women';
  31. this.age = age || 18;
  32. }
  33. var woman = new Women();
  34. console.log(woman.name)
  35. console.log(woman.hello())
  36. console.log('---------------');
  37. // console.log(woman.say()) // 报错
  38. // 3 实例继承 为父类实例添加新特性,作为子类实例返回
  39. function NormalMen (name, age) {
  40. var instance = new Person();
  41. instance.name = name || 'normalMen';
  42. instance.age = age || 18;
  43. return instance;
  44. }
  45. var normalMen = new NormalMen();
  46. console.log(normalMen.name)
  47. console.log(normalMen.hello())
  48. console.log(normalMen.say())
  49. console.log('---------------');
  50. // 4 拷贝继承
  51. function innormalMen(name) {
  52. var person = new Person();
  53. for(var key in person) {
  54. innormalMen[key] = person[key]
  55. }
  56. this.name = name|| 'Tom';
  57. }
  58. var innormalMen = new innormalMen();
  59. console.log(innormalMen.name)
  60. // console.log(innormalMen.say()) // 不可枚举方法不存在
  61. // console.log(innormalMen.hello()) // 不可枚举方法不存在
  62. console.log('---------------');
  63. // 5 组合继承 通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
  64. function WhiteMan(name) {
  65. Person.call(this);
  66. this.name = name || 'jim';
  67. }
  68. WhiteMan.prototype = new Person();
  69. WhiteMan.prototype.constructor = WhiteMan; // 修复构造函数指向
  70. var whiteMan = new WhiteMan('white');
  71. console.log(whiteMan.name)
  72. console.log(whiteMan.hello())
  73. console.log(whiteMan.say())
  74. // 6 寄生组合继承 通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
  75. function YellowMan(name){
  76. Person.call(this);
  77. this.name = name || 'Tom';
  78. }
  79. (function(){
  80. // 创建一个没有实例方法的类
  81. var Super = function(){};
  82. Super.prototype = Person.prototype;
  83. //将实例作为子类的原型
  84. YellowMan.prototype = new Super();
  85. })();
  86. console.log('---------------------------------------------------------------');
  87. // class
  88. class Student {
  89. constructor(name) {
  90. this.name = name;
  91. }
  92. // 实例方法
  93. say() {
  94. console.log(`my name is ${this.name}`)
  95. }
  96. // 静态方法
  97. static create(name) {
  98. return new Person(name)
  99. }
  100. }
  101. // 继承
  102. class GirlStudent extends Student {
  103. constructor(name, num) {
  104. super(name); // 调用父类的构造函数
  105. this.num = num;
  106. }
  107. hello() {
  108. super.say();
  109. console.log(`my student number is ${this.num}`)
  110. }
  111. }
  112. const s = new GirlStudent('lili', 2222);
  113. s.hello()

19 set对象

  1. const s = new Set();
  2. // 添加
  3. s.add(1).add(2).add(3).add(4).add(2);
  4. console.log(s) // Set { 1, 2, 3, 4 }
  5. // 遍历
  6. s.forEach(i => {
  7. console.log(i)
  8. });
  9. // 1
  10. // 2
  11. // 3
  12. // 4
  13. // 长度
  14. console.log(s.size)
  15. // 4
  16. // 删除
  17. console.log(s.delete(3))
  18. // true
  19. // 清除
  20. s.clear();
  21. console.log(s)
  22. // Set {}
  23. const arr = [1,2,3,4,2,1]
  24. // 去重
  25. const aa = new Set(arr);
  26. // 生成新数组
  27. const rr = Array.from(new Set(arr))
  28. // 解构新数组
  29. const dd = [...new Set(arr)]
  30. console.log(aa)
  31. // Set { 1, 2, 3, 4 }
  32. console.log(rr)
  33. // [ 1, 2, 3, 4 ]
  34. console.log(dd)
  35. // [ 1, 2, 3, 4 ]

20 map对象

  1. // map 可以用任意类型的数据作为key
  2. const m = new Map();
  3. const tom = {a :'1'};
  4. // 添加
  5. m.set(tom,10);
  6. console.log(m) //Map { { a: '1' } => 10 }
  7. // 获取
  8. console.log(m.get(tom)) // 10
  9. // 删除
  10. m.delete(tom);
  11. console.log(m) // Map {}
  12. m.set(tom,20);
  13. // 查找
  14. console.log(m.has(tom)) // true
  15. // 遍历
  16. m.forEach((value, key) => {
  17. console.log(value, key)
  18. })
  19. // 20 { a: '1' }
  20. // 清空
  21. m.clear();
  22. console.log(m) // Map {}

20 symbol数据类型
js中基本的数据类型 string, number, boolean, null, undefined, object, symbol, bigInt(es2019)

  1. // symbol 数据类型 表示一个独一无二的值 主要用在给对象添加一个唯一属性名
  2. // 基本的数据类型 string, number, boolean, null, undefined, object, symbol, bigInt(es2019)
  3. const cache = {};
  4. // 在a.js中 定义一个对象值
  5. cache['foo'] = Math.random();
  6. // 在b.js中 定义同名的值导致会被覆盖
  7. cache['foo'] = '123';
  8. console.log(cache) // { foo: '123' }
  9. const ss = Symbol();
  10. console.log(ss);
  11. console.log(typeof ss)
  12. // Symbol()
  13. // symbol
  14. console.log(Symbol('a'))
  15. console.log(Symbol('b'))
  16. console.log(Symbol('c'))
  17. // Symbol(a)
  18. // Symbol(b)
  19. // Symbol(c)
  20. const a = {};
  21. // 以symbol为key
  22. a[Symbol()] = '1'
  23. a[Symbol()] = '2'
  24. console.log(a)
  25. // { [Symbol()]: '1', [Symbol()]: '2' }
  26. // 计算属性
  27. const obj = {
  28. [Symbol()]: 123
  29. };
  30. console.log(obj)
  31. // { [Symbol()]: 123 }
  32. // 私有成员
  33. const name = Symbol();
  34. const person = {
  35. [name] : 'Jason',
  36. say() {
  37. console.log(this.name)
  38. }
  39. }
  40. person.say(); // undefined
  41. console.log(
  42. Symbol() === Symbol(), // false
  43. Symbol('foo') === Symbol('foo'), // false
  44. )
  45. // 相同的symbol值 for方法接受字符串,如果true和'true',则是同一个
  46. const s1 = Symbol.for('foo')
  47. const s2 = Symbol.for('foo')
  48. console.log(s1 === s2) // true
  49. // 内置的symbol常量
  50. console.log(Symbol.hasInstance) // Symbol(Symbol.hasInstance)
  51. console.log(Symbol.iterator); // Symbol(Symbol.iterator)
  52. // 自定义对象标签
  53. const xobj = {
  54. [Symbol.toStringTag] : 'XObject'
  55. }
  56. console.log(xobj.toString()) // [object XObject]
  57. // symbol 定义的key是无法用for...in循环得到的 无法用Object.keys获取,也会被JSON.stringify忽略
  58. const yobj = {
  59. [Symbol()]: 'Symbol',
  60. foo: 11
  61. }
  62. for(let key in yobj) {
  63. console.log(key)
  64. }
  65. console.log(Object.keys(yobj))
  66. console.log(JSON.stringify(yobj))
  67. // 想要获取 getOwnPropertySymbol() 只能获取到symbol属性
  68. console.log(Object.getOwnPropertySymbols(yobj))

21 for…of循环

  1. // for...of循环是一种数据遍历的统一方式
  2. const arr = [100, 200, 300, 400];
  3. for (let item of arr) {
  4. console.log(item);
  5. if (item > 100) {
  6. break;
  7. }
  8. }
  9. // 100
  10. // 200
  11. // forEach无法break
  12. console.log('---------------')
  13. const s = new Set(arr);
  14. for(const item of s) {
  15. console.log(item)
  16. }
  17. // 100
  18. // 200
  19. // 300
  20. // 400
  21. console.log('---------------')
  22. const m = new Map();
  23. m.set('top', 1)
  24. m.set('bottom', 2)
  25. for(const item of m) {
  26. console.log(item)
  27. }
  28. // [ 'top', 1 ]
  29. // [ 'bottom', 2 ]
  30. for(const [key, value] of m) {
  31. console.log(key, value)
  32. }
  33. // top 1
  34. // bottom 2
  35. console.log('---------------')
  36. const o = {a: 1, b: 2, c: 3};
  37. for(const item of o) {
  38. console.log(item)
  39. }
  40. // TypeError: o is not iterable

22 可迭代接口 实现了iterable接口就可以被for…of遍历;在之前的可以被for…of循环例子中,这些对象原型方法上都有Symbol.iterator方法

  1. const set = new Set(['Jason', 'Jhon', 'Jim', 'Tom']);
  2. const iterator = set[Symbol.iterator]();
  3. console.log(iterator.next());
  4. console.log(iterator.next());
  5. console.log(iterator.next());
  6. console.log(iterator.next());
  7. console.log(iterator.next());
  8. console.log(iterator.next());
  9. // { value: 'Jason', done: false }
  10. // { value: 'Jhon', done: false }
  11. // { value: 'Jim', done: false }
  12. // { value: 'Tom', done: false }
  13. // { value: undefined, done: true }
  14. // { value: undefined, done: true }
  15. // 如何实现可迭代接口
  16. const obj = { // iterable
  17. store: ['Jason', 'Jhon', 'Jim', 'Tom'],
  18. [Symbol.iterator]: function() {
  19. let index = 0;
  20. const self = this;
  21. return { // iterator
  22. next: function() {
  23. const result = { // iterationResult
  24. value: self.store[index],
  25. done: index>=self.store.length
  26. }
  27. index ++;
  28. return result;
  29. }
  30. }
  31. }
  32. }
  33. for(const item of obj) {
  34. console.log(item)
  35. }

23 迭代器的意义

  1. // 迭代器接口的意义
  2. const todoList = {
  3. today: ['1','2','3','4'],
  4. tomorrow: ['6','7','8','9'],
  5. afterTomorrow: ['11','12','13','14'], // 后续增加了
  6. forEach: function(callback) { // 提供统一forEach接口
  7. const arr = [].concat(this.today, this.tomorrow,this.afterTomorrow)
  8. for(const item of arr) {
  9. callback(item)
  10. }
  11. },
  12. [Symbol.iterator]: function() {
  13. const arr = [...this.today, ...this.tomorrow, ...this.afterTomorrow];
  14. let index = 0;
  15. return {
  16. next: function() {
  17. return {
  18. value: arr[index],
  19. done: index++>=arr.length
  20. }
  21. }
  22. }
  23. }
  24. }
  25. // 要遍历
  26. for(const item of todoList.today) {
  27. console.log(item)
  28. }
  29. // 要遍历
  30. for(const item of todoList.tomorrow) {
  31. console.log(item)
  32. }
  33. // 此时如果todoList中增加了afterTomorrow就必须重新写
  34. for(const item of todoList.tomorrow) {
  35. console.log(item)
  36. }
  37. // 如果添加了统一的forEach方法就可以减少耦合
  38. todoList.forEach(function(item){
  39. console.log(item)
  40. });
  41. console.log('------------------------------')
  42. // 用迭代器实现
  43. for(const item of todoList) {
  44. console.log(item)
  45. }

24 生成器函数 generator

  1. // 生成器函数
  2. function* foo() {
  3. console.log('foo start')
  4. return 100
  5. }
  6. // 第一次执行初始化一个生成器对象
  7. const result = foo();
  8. console.log(result) // Object [Generator] {}
  9. console.log(result.next())
  10. console.log('------------------------')
  11. // foo start
  12. // { value: 100, done: true }
  13. // 调用生成器对象的next方法,才会走下一步,生成器函数也实现了iteratable接口
  14. // 配合yield使用
  15. function* fn() {
  16. console.log('1')
  17. yield 100;
  18. console.log('2')
  19. yield 200;
  20. console.log('3')
  21. yield 300;
  22. }
  23. const fnResult = fn();
  24. console.log(fnResult.next())
  25. console.log(fnResult.next())
  26. console.log(fnResult.next())
  27. console.log(fnResult.next())
  28. console.log('------------------------')
  29. // 1
  30. // { value: 100, done: false }
  31. // 2
  32. // { value: 200, done: false }
  33. // 3
  34. // { value: 300, done: false }
  35. // { value: undefined, done: true }
  36. // 惰性执行
  37. // 案例1
  38. function* createIdMaker() {
  39. let id = 0;
  40. while(true) {
  41. yield id++;
  42. }
  43. }
  44. const idMaker = createIdMaker();
  45. console.log(idMaker.next())
  46. console.log(idMaker.next())
  47. console.log(idMaker.next())
  48. console.log(idMaker.next())
  49. console.log('------------------------')
  50. // 案例2
  51. const todoList = {
  52. today: ['1', '2', '3', '4'],
  53. tomorrow: ['6', '7', '8', '9'],
  54. afterTomorrow: ['11', '12', '13', '14'], // 后续增加了
  55. forEach: function (callback) {
  56. // 提供统一forEach接口
  57. const arr = [].concat(this.today, this.tomorrow, this.afterTomorrow);
  58. for (const item of arr) {
  59. callback(item);
  60. }
  61. },
  62. // [Symbol.iterator]: function() {
  63. // const arr = [...this.today, ...this.tomorrow, ...this.afterTomorrow];
  64. // let index = 0;
  65. // return {
  66. // next: function() {
  67. // return {
  68. // value: arr[index],
  69. // done: index++>=arr.length
  70. // }
  71. // }
  72. // }
  73. // }
  74. // 用生成器函数代替
  75. [Symbol.iterator]: function* () {
  76. const arr = [...this.today, ...this.tomorrow, ...this.afterTomorrow];
  77. for(const item of arr) {
  78. yield item
  79. }
  80. },
  81. };
  82. for(const item of todoList) {
  83. console.log(item)
  84. }

25 ES modules 模块化
26 es2016

  1. const arr = ['Jason', 'Tom', 'Jim', 'Rich'];
  2. // 判断是否存在foo 是否等于-1
  3. console.log(arr.indexOf('foo')); // -1
  4. console.log(arr.indexOf('Tom')); // 1
  5. // 在es2016中年引入了includes
  6. console.log(arr.includes('foo')); // false
  7. console.log(arr.includes('Tom')); // true
  8. // 指数运算
  9. let a = 2;
  10. console.log(Math.pow(a, 10)); // 1024
  11. // es2016中引入了** 为指数运算符
  12. console.log(2 ** 10); // 1024

27 es2017

  1. const foo = {
  2. name: 'Jason',
  3. age: 20
  4. }
  5. // 1 Object.values
  6. console.log(Object.values(foo)) // [ 'Jason', 20 ]
  7. // 2 Object.entries
  8. console.log(Object.entries(foo)) // [ [ 'name', 'Jason' ], [ 'age', 20 ] ]
  9. // 延伸 普通对象的for...of循环
  10. for(const [key, value] of Object.entries(foo)) {
  11. console.log(key, value)
  12. }
  13. // name Jason
  14. // age 2
  15. // 普通对象转换为map对象
  16. console.log(new Map(Object.entries(foo)))
  17. //Map { 'name' => 'Jason', 'age' => 20 }
  18. // 3 Object.getOwnPropertyDescription
  19. const p1 = {
  20. firstName: 'Lee',
  21. lastName: 'Jason',
  22. get fullName() {
  23. return this.firstName + '.' + this.lastName
  24. }
  25. }
  26. console.log(p1.fullName) // Lee.Jason
  27. // 用Object.assign复制属性后重置
  28. const p2 = Object.assign({}, p1)
  29. p2.lastName = 'Tom'
  30. // Object.assign 不能复制get/set属性
  31. console.log(p2) // { firstName: 'Lee', lastName: 'Tom', fullName: 'Lee.Jason' }
  32. // 如何解决?
  33. const des = Object.getOwnPropertyDescriptors(p1);
  34. // console.log(des);
  35. const p3 = Object.defineProperties({}, des);
  36. p3.lastName = 'Jim';
  37. console.log(p3.fullName) // Lee.Jim
  38. // 4 字符串方法 padStart/padEnd
  39. let a = '>';
  40. let b = '<';
  41. const logTitle = 'request log'
  42. console.log(`${a.padStart(16,'-')} ${logTitle} ${b.padEnd(16,'-')}`)
  43. // ---------------> request log <---------------
  44. // 5 数组末尾允许添加尾逗号
  45. const arr = [
  46. 1,
  47. 2,
  48. 3,
  49. 4,
  50. 5,
  51. ]
  52. // 6 async await