【ES6】学ES6一篇就够了

ES6

let 声明变量

let 关键字声明变量是在 es6 中引入的 ,使用 let 声明变量主要有以下特点:

  • 使用 let 声明的变量具有块级作用域
  • 使用 let 声明的变量没有变量提升
  • 使用 let 声明的变量具有暂时性死区
  • let 声明的变量不能重复声明

const

const 是 ES6 新增的关键字,作用是声明一个只读的常量。注意,常量标识符一般用大写字母表示,使用 const 声明常量主要有以下特点:

  • 声明时必须立即赋值,之后不允许修改常量值
  • 不允许重复声明
  • 块儿级作用域
  • 不存在变量提升

解构赋值

解构赋值是对赋值运算符的扩展。他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取

  • 数组模型的解构(Array)
    基本
let [a, b, c] = [1, 2, 3] // a = 1 // b = 2 // c = 3

可嵌套

let [a, [[b], c]] = [1, [[2], 3]] // a = 1 // b = 2 // c = 3

可忽略

let [a, , b] = [1, 2, 3] // a = 1 // b = 3

不完全解构

let [a = 1, b] = [] // a = 1, b = undefined

剩余运算符

let [a, ...b] = [1, 2, 3] //a = 1 //b = [2, 3]

字符串等在数组的解构中,解构的目标若为可遍历对象,皆可进行解构赋值。可遍历对象即实现 Iterator 接口的数据。

let [a, b, c, d, e] = 'hello' // a = 'h' // b = 'e' // c = 'l' // d = 'l' // e = 'o'

解构默认值

let [a = 2] = [undefined] // a = 2

当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。

let [a = 3, b = a] = [] // a = 3, b = 3
let [a = 3, b = a] = [1] // a = 1, b = 1
let [a = 3, b = a] = [1, 2] // a = 1, b = 2
  • 对象模型的解构(Object)
    基本
let { foo, bar } = { foo: 'aaa', bar: 'bbb' } // foo = 'aaa' // bar = 'bbb'
let { baz: foo } = { baz: 'ddd' } // foo = 'ddd

可嵌套可忽略

let obj = { p: ['hello', { y: 'world' }] }
let {
  p: [x, { y }]
} = obj // x = 'hello' // y = 'world'
let obj = { p: ['hello', { y: 'world' }] }
let {
  p: [x, {}]
} = obj // x = 'hello'

不完全解构

let obj = { p: [{ y: 'world' }] }
let {
  p: [{ y }, x]
} = obj // x = undefined // y = 'world'

剩余运算符

let { a, b, ...rest } = { a: 10, b: 20, c: 30, d: 40 } // a = 10 // b = 20 // rest = {c: 30, d: 40}

解构默认值

let { a = 10, b = 5 } = { a: 3 } // a = 3; b = 5;
let { a: aa = 10, b: bb = 5 } = { a: 3 } // aa = 3; bb = 5;

模板字符串

模板字符串相当于加强版的字符串,用反引号 ,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。
多行字符串:

let string1 = `Hey, can you stop angry now?`
console.log(string1) // Hey, // can you stop angry now?

字符串插入变量和表达式。变量名写在 中 , {} 中, {} 中可以放入 JavaScript 表达式。

let name = 'Mike'
let age = 27
let info = `My Name is ${name},I am ${age + 1} years old next year.`
console.log(info)
// My Name is Mike,I am 28 years old next year.

字符串中调用函数:

function f() {
  return 'have fun!'
}
let string2 = `Game start,${f()}`
console.log(string2)
// Game start,have fun!

注意要点:
模板字符串中的换行和空格都是会被保留的
标签模板
是一个函数的调用,其中调用的参数是模板字符串。

alert`Hello world!`
// 等价于
alert('Hello world!')

字符串与数值拓展

  • 字符串

includes():返回布尔值,判断是否找到参数字符串。
startsWith():返回布尔值,判断参数字符串是否在原字符串的头部。
endsWith():返回布尔值,判断参数字符串是否在原字符串的尾部。
注意点:
这三个方法只返回布尔值,如果需要知道子串的位置,还是得用 indexOf 和 lastIndexOf 。这三个方法如果传入了正则表达式而不是字符串,会抛出错误。而 indexOf 和 lastIndexOf 这两个方法,它们会将正则表达式转换为字符串并搜索它。
以上三个方法都可以接受两个参数,需要搜索的字符串,和可选的搜索起始位置索引
repeat():返回新的字符串,表示将字符串重复指定次数返回。
padStart:返回新的字符串,表示用参数字符串从头部(左侧)补全原字符串。
padEnd:返回新的字符串,表示用参数字符串从尾部(右侧)补全原字符串。
以上两个方法接受两个参数,第一个参数是指定生成的字符串的最小长度,第二个参数是用来补全的字符串。如果没有指定第二个参数,默认用空格填充。

console.log('h'.padStart(5, 'o')) // "ooooh"
console.log('h'.padEnd(5, 'o')) // "hoooo"
console.log('h'.padStart(5)) // "    h"
  • 数值
    二进制表示法新写法: 前缀 0b 或 0B 。
    八进制表示法新写法: 前缀 0o 或 0O 。
    Number.EPSILON 属性表示 1 与大于 1 的最小浮点数之间的差。它的值接近于 2.2204460492503130808472633361816E-16,或者 2-52。测试数值是否在误差范围内:
0.1 + 0.2 === 0.3 // false// 在误差范围内即视为相等
equal = Math.abs(0.1 - 0.3 + 0.2) < Number.EPSILON // true

最大/最小安全整数
安全整数安全整数表示在 JavaScript 中能够精确表示的整数,安全整数的范围在 2 的 -53 次方到 2 的 53 次方之间(不包括两个端点),超过这个范围的整数无法精确表示。
最大安全整数安全整数范围的上限,即 2 的 53 次方减 1 。
最小安全整数安全整数范围的下限,即 2 的 53 次方减 1 的负数。

  • 方法
    Number.isFinite():用于检查一个数值是否为有限的( finite ),即不是 Infinity
    从全局移植到 Number 对象的方法逐步减少全局方法,用于全局变量的模块化。方法的行为没有发生改变。Number.parseInt()用于将给定字符串转化为指定进制的整数。
    Math.cbrt 用于计算一个数的立方根。
    Math.imul 两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
    Math.hypot 用于计算所有参数的平方和的平方根。
    Math.clz32 用于返回数字的 32 位无符号整数形式的前导 0 的个数。
    Math.trunc 用于返回数字的整数部分
    Math.fround 用于获取数字的 32 位单精度浮点数形式。
    Math.sign 判断数字的符号(正、负、0)
    Math.expm1()用于计算 e 的 x 次方减 1 的结果,即 Math.exp(x) - 1

    详见ECMAScript 6.0

数组拓展

  • array.forEach()
    循环遍历数组中的每一项
let arr = [1,2,3]
array.forEach((item,index)=>{//数组操作不能return 值})
  • array.map()
    map 方法和 forEach 每次执行匿名函数都支持 3 个参数,参数分别是 item(当前每一项)、index(索引值)、arr(原数组),但是 map 返回一个新数组,原数组不影响;
let arr = [1, 2, 3]
let arr2 = arr.map((iitem, index) => {
  if (item == 1) {
    return true
  } else {
    return false //通过return 返回想要的东西
  }
})
  • array.filter 筛选数组中符合条件的项,返回一个新数组
let arr = [1,2,4];
let result = arr.filter((item,index)=>{return item>2;}
  • array.some()和 array.every()
    一个数组是否满足什么条件,返回一个布尔值
let arr = [1,2,4];let result = arr.some((item,index)=>{return item>2;}//true
let arr = [1,2,4];let result = arr.every((item,index)=>{return item>2;}//false
  • array.find()find()
    方法只会找到第一个符合的,找到之后就会直接返回,就算下面还有符合要求的,也不会再找下去
  • reduce()
    reduce()方法,一般用于求和,它是一个比较特殊的方法,一共有四个参数。 reduce()方法最重要的作用就是累加的操作,将数组的每个元素从左往右依次执行累加器,返回最终的处理结果。不会影响原数组。
let arr = [1, 2, 3, 4]
// sum:上一次的值,item:当前值,index:当前索引,arr:原数组
const result = arr.reduce((sum, item, index, arr) => {
  return (sum += item)
}, 0)
// 这里的0,是一个初始值,意思是从0开始计算
// 因为我这里做的是加法运算,所以返回的是累加的和
console.log(result) // 10

对象拓展

  • Object.assign()
    通过复制一个或多个对象来创建一个新的对象
    如果目标对象和源对象有同名属性,或者多个源对象有同名属性,则后面的属性会覆盖前面的属性。如果该函数只有一个参数,当参数为对象时,直接返回该对象;当参数不是对象时,会先将参数转为对象然后返回。
    assign 的属性拷贝是浅拷贝
    拓展运算符(…)用于取出参数对象所有可遍历属性然后拷贝到当前对象。自定义的属性在拓展运算符后面,则拓展运算符对象内部同名的属性将被覆盖掉。
  • Object.is(value1, value2)
    用来比较两个值是否严格相等,与(===)基本类似。
Object.is(+0, -0) //false
;+0 === -0 //true
Object.is(NaN, NaN) //true
NaN === NaN //false
  • Object.defineProperty()
    方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
    Object.defineProperty(obj, prop, descriptor)
    obj 要定义属性的对象。
    prop 要定义或修改的属性的名称或 Symbol 。
    descriptor 要定义或修改的属性描述符。
数据描述符:
Configurable:能否delete删除属性(默认值false)
Writable: 能否修改属性的值(默认值false)
Value: 属性的值 (默认值undefined)
Enumerable: 该属性是否为可枚举 (默认值false)
存取描述符:
存取描述符属性 Enumerable 和 Configurable 和数据描述符一致
Get: 提供一个getter方法,访问调用
Set: 提供一个setter方法,修改时调用
// Object.defineProperty
  var  obj = new Object()
  Object.defineProperty(obj, "name",{
    Configurable : false ,
    Enumerable: true ,
    Writable: false,
    Value: "无法被修改的值"
})
console.log(obj.name) // 无法被修改的值
  • Object.defineProperties(obj.props)
    将所有可枚举属性的值从一个或多个对象复制到目标对象,并返回目标对象
  • Object.getOwnPropertyDescriptor(obj,prop)
    获取对象中的一个属性描述
    参数:obj:目标对象 prop:目标属性名称
  • Object.getOwnPropertyDescriptors(obj)
    获取目标对象中的所有属性描述,如果没有任何自身属性,则返回空对象
  • Object.entries(obj)
    返回自身可枚举属性的键值对,顺序与 for in 一致,返回一个二维数组 [[key:value]]
  • Object.freeze(obj)
    冻结:一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性 Enumerable、可配置性 Configurable、可写性 Writable,以及不能修改已有属性的值 Value。此外,冻结一个对象后该对象的原型也不能被修改。
  • Object.isFrozen(obj)
    返回布尔值,判断对象是否被冻结
  • Object.getOwnPropertyNames(obj)
    返回指定对象所有属性,同时也包括不可枚举属性组成的数组(该方法无法返回对象 Symbol 属性)
  • Object.keys(obj)
    获取一个对象中所有的 key 值 (除了不可枚举属性和 Symbol 属性)
  • Object.getOwnPropertySymbols(obj)
    返回一个给定对象自身的所有 Symbol 属性的数组
  • Object.getPrototypeOf(obj)
    返回指定对象的原型对象
  • Object.is(Value1 , Value2)
    判断两个值是否为"相同的值"
    相同的值: 1.都是 undefined、true、false、null 2.相同字符串 3.相同对象,且处于同一个引用
  • Object.isExtensible(obj)
    判断对象是否具备可扩展性,返回布尔值
  • Object.setPrototypeOf(obj,property)
    obj: 目标对象
    property: 新原型(对象)
    注意: 应该避免更改对象的 property,这会影响其性能,相反,可以使用 Object.create()来创建你想要[[prototyoe]]新对象
  • Object.create(obj,propertiesObject)
    创建一个新对象,使用现有的对象来提供新创建对象的proto
  • Object.isSealed(obj)
    返回 boolean, 判断对象是否为封闭对象
  • Object.Seal(obj)
    封闭对象:无法删除旧属性或添加新属性,但是可以修改旧属性
  • typeoftypeof
    常用来判断基本数据类型,无法做到准确的判断对象类型,返回值字符串
  • instanceof
    ES 6 新增,为了解决 typeof 无法检查出具体对象类型,返回布尔值
    instanceof 的本质:检测构造函数(右边)的 prototype 属性是否出现在某个实例对象(左边)的原型链上
    语法:Object instanceof Contrusctor
    Object : 实例对象
    Contrusctor:构造函数
    contructor 它始终指向它的构造函数
    缺陷:undefined 和 null 都是无效的对象,没有 contructor 属性,所以无法判断
  • Object.prototype.toString.call()
    通过 Object.prototype.toString 返回对象类型字符串,判断类型
    建议:加上 call() 改变 this 指向,因为如果在原型上定义了 toString 方法,this 的指向会指向为原型定义的方法,可能达不到预期目的

函数扩展

  • 参数默认值
function aaa(a = 'aaa') {
  console.log(a)
}
aaa() //结果:aaa
  • rest 参数剩余参数
function test() {
  console.log(arguments)
}
test(1, 2, 3, 4, 5) //1,2,3,4,5
function test(...arg) {
  console.log(arg)
}
test(1, 2, 3, 4, 5) //1,2,3,4,5
  • name 属性
    console.log(test.name) //test
  • 箭头函数
let test = () => {
  console.log('test')
}
test() //test
let test1 = () => '11111111'
console.log(test1) //11111111

如果只有一个参数可以省略()
无法访问 arguments 无法 new
this 没用 this,this 指向父作用域

symbol

Symbol 是 ES6 中引入的一种新的基本数据类型,用于表示一个独一无二的值。它是 JavaScript 中的第七种数据类型,与 undefined、null、Number(数值)、String(字符串)、Boolean(布尔值)、Object(对象)并列。

// 创建Symbol
let s1 = Symbol()
console.log(s1, typeof s1)
// 添加标识的Symbol
let s2 = Symbol('张三')
let s2_2 = Symbol('张三')
console.log(s2 === s2_2) //false
// 使用Symbol for定义
let s3 = Symbol.for('张三')
let s3_2 = Symbol.for('张三')
console.log(s3 === s3_2) //true,使用symbol.for()来实现

Iterator 迭代器

Iterator 的作用有三个:
一是为各种数据结构,提供一个统一的、简便的访问接口;
二是使得数据结构的成员能够按某种次序排列;
三是 ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 循环
Iterator 的遍历过程是这样的:
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的 next 方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的 next 方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的 next 方法,直到它指向数据结构的结束位置。

let i = arr[Symbol.iterator]()
console.log(i.next())
console.log(i.next())
console.log(i.next())
console.log(i.next())

ES6 规定,默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,或者说,一个数据结构只要具有 Symbol.iterator 属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator 属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。
原生默认具备 Iterator 接口的数据结构如下:
Array、Set、Map、String、arguments 对象、NodeList 对象
使对象可迭代

const obj = {
  code: 200,
  mas: 'test',
  data: [1, 2, 3, 7, 8, 9],
  [Symbol.iterator]() {
    let index = 0
    return {
      next: () => {
        return {
          value: this.data[index++],
          done: index === this.data.length + 1 ? true : false
        }
      }
    }
  }
}
console.log([...obj])
const iter = obj[Symbol.iterator]()
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())

Set 结构

它类似于数组,但成员的值都是唯一的,没有重复的值。
size:返回 Set 实例的成员总数。
Set.prototype.add(value):添加某个 value。
Set.prototype.delete(value):删除某个 value,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为 Set 的成员。
Set.prototype.clear():清除所有成员,没有返回值。
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():遍历每个成员

  • 复杂数据结构去重
function uni(arr) {
  let res = new Set()
  return arr.filter((item) => {
    let id = JSON.stringify(item)
    if (res.has(id)) {
      return false
    } else {
      res.add(id)
      return true
    }
  })
}

Map 结构

类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
size:返回 Map 结构的成员总数。
Map.prototype.set(key,value):添加 key 对应得 value,返回 Map 结构本身。
Map.prototype.get(key):获取 key 对应的 value
Map.prototype.delete(key):删除某个键(键名+键值)
Map.prototype.has(key):某个键是否在当前 Map 对象之中。
Map.prototype.clear():清除所有成员,没有返回值。
Map.prototype.keys():返回键名的遍历器。
Map.prototype.values():返回键值的遍历器。
Map.prototype.entries():返回所有成员的遍历器。
Map.prototype.forEach():遍历 Map 的所有成员

Proxy 代理

Proxy 如其名, 它的作用是在对象和和对象的属性值之间设置一个代理,获取该对象的值或者设置该对象的值, 以及实例化等等多种操作, 都会被拦截住, 经过这一层我们可以统一处理,我们可以认为它就是“代理器”

  • get 方法
let target = {}
let proxy = new Proxy(target, {
  get(target, prop) {
    return target[prop]
  }
})
  • set 方法
let target = {}
let proxy = new Proxy(target, {
  get(target, prop) {
    return target[prop]
  },
  set(target, prop, value) {
    if (prop === 'data') {
      box.innerHTML = value
    }
    target[prop] = value
  }
})
  • has 方法
let target = {
  _prop: '内部数据'
}
let proxy = new Proxy(target, {
  get(target, prop) {
    return target[prop]
  },
  set(target, prop, value) {
    if (prop === 'data') {
      box.innerHTML = value
    }
    target[prop] = value
  },
  has(target, key) {
    if (key[0] === '_') {
      return false
    }
    return key in target
  }
})
  • this 问题
let target = new Set()
const proxy = new Proxy(target, {
  get(target, key) {
    const value = target[key] // 遇到 Function 都手动绑定一下 this
    if (value instanceof Function) {
      console.log(`访问${value}方法了`)
      return value.bind(target) //不能 是 call apply
    }
    return value
  }
})
proxy.add(1)

Proxy 本质上属于元编程非破坏性数据劫持,在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念。

Reflect 对象

Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

  • Object 的某些方法
const obj = {}
Reflect.defineProperty(obj, 'name', {
  value: 'kerwin',
  writable: false,
  configurable: false
})
  • 修改某些 Object 方法返回结果
// 老写法
try {
  Object.defineProperty(target, property, attributes) // success
} catch (e) {
  // fail
}
// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // fail
}
  • 命令式变为函数行为
const obj = {
  name: 'kerwin'
}
//老写法
console.log('name' in obj) //true
//新写法
console.log(Reflect.has(obj, 'name')) //true
//老写法
delete obj.name
//新写法
Reflect.deleteProperty(obj, 'name')
  • 配合 Proxy
let target = new Set()
const proxy = new Proxy(target, {
  get(target, key) {
    const value = Reflect.get(target, key) // 遇到 Function 都手动绑定一下 this
    if (value instanceof Function) {
      console.log(`访问${value}方法了`)
      return value.bind(target) //不能 是 call apply
    }
    return value
  },
  set() {
    return Reflect.set(...arguments)
  }
})
proxy.add(1)
let arr = [1, 2, 3]
let proxy = new Proxy(arr, {
  get(target, key) {
    console.log('get', key)
    return Reflect.get(...arguments)
  },
  set(target, key, value) {
    console.log('set', key, value)
    return Reflect.set(...arguments)
  }
})
proxy.push(4)
// 能够打印出很多内容
// get push     (寻找 proxy.push 方法)
// get length   (获取当前的 length)
// set 3 4      (设置 proxy[3] = 4)
// set length 4 (设置 proxy.length = 4)

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案回调函数, 更合理和更强大。ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象 。
指定回调函数方式更灵活易懂。
解决异步 回调地狱 的问题。
回调地狱
当一个回调函数嵌套一个回调函数的时候
就会出现一个嵌套结构
当嵌套的多了就会出现回调地狱的情况
比如我们发送三个 ajax 请求
第一个正常发送
第二个请求需要第一个请求的结果中的某一个值作为参数
第三个请求需要第二个请求的结果中的某一个值作为参数

ajax({
  url: '我是第一个请求',
  success (res) {
    // 现在发送第二个请求
    ajax({
      url: '我是第二个请求',
      data: { a: res.a, b: res.b },
      success (res2) {
        // 进行第三个请求
        ajax({
          url: '我是第三个请求',
          data: { a: res2.a, b: res2.b },
              success (res3) {
            console.log(res3)
          }
        })
      }
    })
  }
})

回调地狱,其实就是回调函数嵌套过多导致的,
当代码成为这个结构以后,已经没有维护的可能了
Promise 使用
语法:

new Promise(function (resolve, reject) {
  // resolve 表示成功的回调
  // reject 表示失败的回调
})
  .then(function (res) {
    // 成功的函数
  })
  .catch(function (err) {
    // 失败的函数
  })

Promise 对象的状态
Promise 对象通过自身的状态,来控制异步操作。Promise 实例具有三种状态:

  • 异步操作未完成(pending)
  • 异步操作成功(fulfilled)
  • 异步操作失败(rejected)

这三种的状态的变化途径只有两种。

  • 从“未完成”到“成功”
  • 从“未完成”到“失败”

一旦状态发生变化,就凝固了,不会再有新的状态变化。这也是 Promise 这个名字的由来,它的英语意思是“承诺”,一旦承诺成效,就不得再改变了。这也意味着,Promise 实例的状态变化只可能发生一次。
因此,Promise 的最终结果只有两种。
异步操作成功,Promise 实例传回一个值(value),状态变为 fulfilled。
异步操作失败,Promise 实例抛出一个错误(error),状态变为 rejected。

  • Promise.all

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
javascript
const p = Promise.all([p1, p2, p3]);
p 的状态由 p1,p2,p3 决定,分成两种情况:
(1)只有 p1、p2、p3 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2、p3 的返回值组成一个数组,传递给 p 的回调函数。
(2)只要 p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。

  • Promise.race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
javascript
const p = Promise.race([p1, p2, p3]);
上面代码中,只要 p1、p2、p3 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。

Generator 函数

Generator 函数是 ES6 提供的一种异步编程解决方案
Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

function* generator() {
  g1 = yield 11
  console.log(g1)
  g2 = yield 22
  console.log(g2)
}
let gen = generator()
let f1 = gen.next(11111111111111)
console.log(f1)
let f2 = gen.next(2222222222222222)
console.log(f2)
let f3 = gen.next(33333333333333333)
console.log(f3)
//object
//2222222222222222
//object
//33333333333333333
//object

yield(产出)表达式是暂停执行的标记,而 next 方法可以恢复执行
异步流程

//手动版本
function* gen() {
  let res1 = yield ajax('1.json')
  console.log(res1)
  let res2 = yield ajax('2.json')
  console.log(res2)
}
let g = gen()
g.next().value.then((data) => {
  g.next(data).value.then((data) => {
    g.next(data)
  })
})
//自动版本
function* gen() {
  let res1 = yield ajax('1.json')
  console.log(res1)
  let res2 = yield ajax('2.json')
  console.log(res2)
}
function AutoRun(gen) {
  let g = gen()
  function next(data) {
    let res = g.next(data)
    if (res.done) return
    res.value.then(function (data) {
      next(data)
    })
  }
  next()
}
AutoRun(gen)

  • 类的写法
  // function Person(name ,age){
  //   this.name=name
  //   this.age=age
  // }
  // Person.prototype.say=function(){
  //   console.log(this.name,this.age);
  // }
  // let obj=new Person("zs",18)
  // obj.say()
  //Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一
  //无二的值。它是JavaScript中的第七种数据类型,与undefined、
  //null、Number(数值)、String(字符串)、Boolean(布尔值)、
  Object(对象)并列。
  let s=Symbol("say")
  class Person{
    constructor(name,age){
      this.name=name
      this.age=age
    }
    [s](){
      console.log(this.name,this.age);
    }
  }
  let obj=new Person("zs",18)
  obj[s]()
  console.log(obj);
  console.log(Person);

注:prototype 是构造函数的一个属性,它指向了一个对象。这个对象的所有属性和方法都可以被该构造函数的实例继承。 proto 是每个对象都有的属性,它指向了这个对象的原型对象。即指向了该对象的构函数的 prototype 属性指向的对象。 总的来说,prototype 是构造函数的属性,proto是对象的属性。

  • get()和 set()方法
<!DOCTYPE html>
<html lang="en">
  <head>
     
    <meta charset="UTF-8" />
     
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
     
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     
    <title>Document</title>
  </head>
  <body>
     
    <ul class="list">
       
    </ul>
     
    <script>
      class Person {
        constructor(name, age, list) {
          this.name = name
          this.age = age
          this.ele = document.querySelector(`.${list}`)
        }
        get age() {
          console.log('get')
        }
        set age(data) {
          console.log('set', data)
        }
        get html() {
          return this.ele.innerHTML
        }
        set html(data) {
          this.ele.innerHTML = data.map((item) => `<li>${item}</li>`).join('')
        }
      }
      let obj = new Person('zs', 18, 'list')
    </script>
  </body>
</html>
  • 静态属性和方法

定在在类上,而不是定义在类的原型上,类可以调用,类的实例不能调用的方法就叫做静态方法在实际应用中,静态方法主要用于操作静态属性。

// 静态属性
class Person {
  // ES6写法
  static myname = 'ls'
  static mySay() {
    console.log(this)
  }
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  say() {
    console.log(this.name, this.age)
  }
} // 普通写法 // Person.myname="ls" // Person.mySay=function(){ //   console.log(this); // }
let obj = new Person('zs', 18)
Person.mySay()
  • 继承

创建的子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。

let s = Symbol('say')
class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  [s]() {
    console.log(this.name, this.age)
  }
} // 继承Person
class Student extends Person {
  constructor(name, age) {
    // super可以理解为父类的,super可以用来调用属性、方法、构造器
    super(name, age)
  }
  getname() {
    console.log(this.name)
  }
}

Module 语法

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

在 ES6 模块化规范诞生之前,JavaScript 社区已经尝试并提出了 AMD、CMD、CommonJS 等模块化规范。
但是,这些由社区提出的模块化标准,还是存在一定的差异性与局限性、并不是浏览器与服务器通用的模块化标准,例如:
AMD 和 CMD 适用于浏览器端的 Javascript 模块化
CommonJS 适用于服务器端的 Javascript 模块化
ES6 模块化规范是浏览器端与服务器端通用的模块化开发规范

  • 模块化的好处:
    ① 阻止命名冲突; ② 代码复用; ③ 高维护性
  • ES6 模块化语法:
    ① export 命令:用于规定模块的对外接口
    ② import 命令:用于输入其他模块提供的功能
  • 默认导出与默认导入
  1. 默认导出的语法:export default
  2. 默认导出的成员默认导入的语法:import 接收名称 from '模块标识符'
  • 按需导入与按需导出
  1. 按需导入语法:export 类型
  2. 成员按需导出语法:import { 成员 } from '模块标识符'
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值