ES6中常见基本知识点的基本使用实例汇总

目录
  • 前言
  • 1、字面量的增强
  • 2、解构Destructuring
  • 3、let和const
  • 4、作用域
  • 5、模板子符串
  • 6、函数
  • 7、展开语法
  • 8、数值表示
  • 9、Symbol的基本使用
  • 10、Set
  • 11、WeakSet
  • 12、Map
  • 13、WeakMap
  • 总结

前言

学习了coderwhy的JavaScript高级语法视频课的笔记

如有错误或者不合适的地方,敬请见谅,欢迎指出和拓展,谢谢各位了

1、字面量的增强

var name = 'xxx'
var age = 12
var obj = {
  // 1.property shorthand(属性的简写)
  name: name,
  age,

  // 2.method shorthand(方法的简写)
  foo: function () {
    console.log(1)
  },

  foo2: () => {
    console.log(2)
  },

  foo3() {
    console.log(3)
  },

  // 3.computed property name(计算属性名)
  [name + 123]: 'yyy'
}

obj.foo() //1
obj.foo2() //2
obj.foo3() //3
obj[name + 456] = 'zzz'
console.log(obj)
// {
//   name: 'xxx',
//   age: 12,
//   foo: [Function: foo],
//   foo2: [Function: foo2],
//   foo3: [Function: foo3],
//   xxx123: 'yyy',
//   xxx456: 'zzz'
// }

2、解构Destructuring

  • 数组解构
var arr = ['aaa', 'bbb', 'ccc']
// 以前的做法
// var a1 = arr[0]
// var a2 = arr[1]
// var a3 = arr[2]

// 1、对数组的解构
var [a1, a2, a3] = arr
console.log(a1, a2, a3) //aaa bbb ccc

// 2、解构后面的元素
var [, , a4] = arr
console.log(a4) //ccc

// 3、解构出一个元素,后面的元素放到一个新数组中
var [a5, ...newArr] = arr
console.log(a5, newArr) //aaa [ 'bbb', 'ccc' ]

// 4、解构的默认值
var [a6, a7, a8, a9 = 'ddd'] = arr
console.log(a6, a7, a8, a9) //aaa bbb ccc ddd
  • 对象解构
var obj = {
  name: 'xxx',
  age: 123,
  address: '广东'
}

//1、全部解构
var { name, age, address } = obj
console.log(name, age, address) //xxx 123 广东

//2、解构单个
var { age } = obj
console.log(age) //123

// 3、重新命名
var { age: newAge } = obj
console.log(newAge) //123

//4、解构的默认值
var { color: newColor = 'red' } = obj
console.log(newColor) //red

//5、函数中
function foo(o) {
  console.log(o.name, o.age) //xxx 123
}
foo(obj)

function foo2({ name, age }) {
  console.log(name, age) //xxx 123
}
foo2(obj)

function foo3({ name, age=456}) {
  console.log(name, age) //xxx 123
}
foo3(obj)

3、let和const

  • 基本语法
// 1、从直观的角度来说,let和var是没有太大的区别的,都是用于声明一个变量
let bar = "bar"

// 2、const constant(常量/衡量)
const name = "abc"

// 3、
// 注意事项一: const本质上是传递的值不可以修改
// 但是如果传递的是一个引用类型(内存地址), 可以通过引用找到对应的对象, 去修改对象内部的属性, 这个是可以的
const obj = {
    foo: "foo"
}

obj2.foo = "aaa"
console.log(obj.foo)// aaa

// 4、
// 注意事项二: 通过let/const定义的变量名是不可以重复定义
// let foo = "abc"
// let foo = "cba"
  • 作用域提升
  • 在执行上下文的词法环境创建出来的时候,变量事实上已经被创建了,只是这个变量是不能被提前访问的。
  • 那么我们自己从字面量上理解:在声明变量的作用域中,如果这个变量可以在声明之前被访问,那么我们可以称之为作用域提升
// 作用域提升: 能提前被访问
console.log(foo)// undefined
var foo = "foo"

// let/const他们是没有作用域提升
// foo被创建出来了, 但是不能被访问
// Reference(引用)Error: Cannot access 'foo' before initialization(初始化)
console.log(foo)
let foo = "foo"
  • let、const和window的关系
  • 我们知道,在全局通过var来声明一个变量,事实上会在window上添加一个属性,但是let、const是不会给window上添加任何属性
  • 基于早期ECMA的版本规范:
    • 每一个执行上下文会被关联到一个变量对象(variable object,VO),在源代码中的变量和函数声明会被作为属性添加到VO中。对与函数来说,参数也会被添加到VO中。
  • 在最新的ECMA的版本规范中,对于一些词汇进行了修改:
    • 每一个执行上下文会被关联到一个变量环境(VariableEnvironment,VE),在执行代码中的变量和函数声明会被作为环境记录(Environment Record)添加到变量环境中。对与函数来说,参数也会被环境记录添加到变量环境中。

也就是说我们声明的变量和环境记录是被添加到变量环境中的,但是标准没有规定这个对象是window对象或者其他对象,那么JS引擎在解析的时候,其实会有自己的实现。比如v8中其实是通过VariableMap的一个hashmap来实现它们的存储的(VE->variables_)。

那么window对象呢?而window对象是早期的GO对象,在最新的实现中其实是浏览器添加的全局对象,并且 一直保持了window和var之间值的相等性。

var a = 123
let b = 456

console.log(window.a) //123
console.log(window.b) //undefined

4、作用域

  • ES5作用域(ES5中没有块级作用域)
// 在ES5中只有两个东西会形成作用域
// 1.全局作用域

// 2.函数(局部)作用域
function foo() {
    var bar = "bar"
}
  • ES6作用域(新增一个块级作用域)
// ES6的代码块级作用域
// 对let/const/function/class声明的类型是有效
{
  let foo = 'why'
  function demo() {
    console.log('demo function')
  }
  class Person {}
}

console.log(foo) // foo is not defined
// 不同的浏览器有不同实现的(大部分浏览器为了兼容以前的代码, 让function是没有块级作用域)
demo() //demo function
var p = new Person() // Person is not defined
// 1、if语句的代码就是块级作用域
if (true) {
  var foo = 'foo'
  let bar = 'bar'
}

console.log(foo) //foo
console.log(bar) //bar is not defined

// 2、switch语句的代码也是块级作用域
var color = 'red'
switch (color) {
  case 'red':
    var foo2 = 'foo'
    let bar2 = 'bar'
}

console.log(foo2) //foo
console.log(bar2) //bar2 is not defined

// 3、for语句的代码也是块级作用域
for (var i = 0; i < 10; i++) {
  console.log('Hello World' + i)
  // Hello World0
  // Hello World1
  // Hello World2
  // Hello World3
  // Hello World4
  // Hello World5
  // Hello World6
  // Hello World7
  // Hello World8
  // Hello World9
}
console.log(i) //10

for (let j = 0; j < 10; j++) {}

console.log(j) //j is not defined
  • 块级作用域的应用场景

点击不同的button打印出不同的button编号的两种实现方法。

const btns = document.getElementsByTagName('button')
// 1、var没有块级作用域
for (var i = 0; i < btns.length; i++) {
  ;(function (n) {
    btns[i].onclick = function () {
      console.log('第' + n + '个按钮被点击')
    }
  })(i)
}

// 2、let有块级作用域
for (let i = 0; i < btns.length; i++) {
  btns[i].onclick = function () {
    console.log('第' + i + '个按钮被点击')
  }
}
  • 块级作用域的补充
const names = ['abc', 'cba', 'nba']

// 1、不可以使用const,因为i的每次循环(生成一个块级作用域)都不一样,其实都是需要上一次的i进行i++赋值给下一个i
for (let i = 0; i < names.length; i++) {
  console.log(names[i])
}

// 2、for...of: ES6新增的遍历数组(对象)
// 因为每次遍历(生成一个块级作用域)的值都赋给一个item,所以不需要上一次item的值进行操作
for (const item of names) {
  console.log(item)
}
  • let和const的暂时性死区

在ES6中,我们还有一个概念称之为暂时性死区:它表达的意思是在一个代码中,使用let、const声明的变量,在声明之前,变量都是不可以访问的,我们将这种现象称之为 temporal dead zone(暂时性死区,TDZ)。

var foo = 'foo'

// 块级作用域
if (true) {
  console.log(foo) //Cannot access 'foo' before initialization

  let foo = 'abc'
}
  • var、let、const的选择
  • 对于var的使用:

    • 我们需要明白一个事实,var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些 历史遗留问题;
    • 其实是JavaScript在设计之初的一种语言缺陷;
  • 对于let、const:
    • 对于let和const来说,是目前开发中推荐使用的;
    • 我们会优先推荐使用const,这样可以保证数据的安全性不会被随意的篡改;
    • 只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let;
    • 这种在很多其他语言里面也都是一种约定俗成的规范,尽量我们也遵守这种规范;

5、模板子符串

  • 基本使用
// ES6之前拼接字符串和其他标识符
const name = 'why'
const age = 18
const height = 1.88

console.log('my name is ' + name + ', age is ' + age + ', height is ' + height)

// ES6提供模板字符串 ``
// 1、
const message = `my name is ${name}, age is ${age}, height is ${height}`
console.log(message)

// 2、
const info = `age double is ${age * 2}`
console.log(info)

// 3、
function doubleAge() {
  return age * 2
}

const info2 = `double age is ${doubleAge()}`
console.log(info2)
  • 标签模板字符串
// 第一个参数依然是模块字符串中整个字符串, 只是被切成多块,放到了一个数组中
// 第二个参数是模块字符串中, 第一个 ${}
function foo(m, n, x) {
  console.log(m, n, x)
}

// 另外调用函数的方式: 标签模块字符串
foo`` //[ '' ] undefined undefined

foo`Hello World` //[ 'Hello World' ] undefined undefined

const name = 'why'
const age = 18
foo`Hello${name}Wo${age}rld` //[ 'Hello', 'Wo', 'rld' ] why 18

6、函数

  • 函数的默认参数
// 1.ES6可以给函数参数提供默认值
function foo(m = 'aaa', n = 'bbb') {
  console.log(m, n)
}

foo(0)// 0 bbb

// 2.对象参数和默认值以及解构
function printInfo({ name, age } = { name: 'why', age: 18 }) {
  console.log(name, age)
}
printInfo({ name: 'kobe', age: 40 }) //kobe 40

// 另外一种写法
function printInfo1({ name = 'why', age = 18 } = {}) {
  console.log(name, age)
}
printInfo1() //why 18

// 3.有默认值的形参最好放到最后
function bar(x, y, z = 30) {
  console.log(x, y, z)
}

bar(10, 20) //10 20 30

// 4.有默认值的函数的length属性
function baz(x, y, z, m, n = 30) {
  console.log(x, y, z, m, n)
}

console.log(baz.length)// 4
  • 函数的剩余次数
function foo(m, n, ...args) {
  console.log(m, n) //20 30
  console.log(args) //[ 40, 50, 60 ]
  console.log(arguments) //[Arguments] { '0': 20, '1': 30, '2': 40, '3': 50, '4': 60 }
}

foo(20, 30, 40, 50, 60)

//function foo (...args,m, n)
// rest paramaters必须放到最后
// Rest parameter must be last formal parameter
  • 箭头函数

箭头函数是没有显式原型的,所以不能作为构造函数,使用new来创建对象。

function foo() {}

console.log(foo.prototype) //{}
const f = new foo()
console.log(f.__proto__) //{}

var bar = () => {
  console.log(this, arguments) //箭头函数本身没有
}

console.log(bar.prototype) //undefined
const f2 = new bar() //bar is not a constructor

7、展开语法

const names = ['abc', 'cba', 'nba']
const name = 'why'
const info = { name: 'why', age: 18 }

// 1.函数调用时
function foo(x, y, z) {
  console.log(x, y, z)
}

// foo.apply(null, names)
foo(...names) //abc cba nba
foo(...name) //w h y

// 2.构造数组时
const newNames = [...names, ...name]
console.log(newNames) //[ 'abc', 'cba', 'nba', 'w', 'h', 'y' ]

// 3.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: '广州市', ...names }
console.log(obj)
// {
//     '0': 'abc',
//     '1': 'cba',
//     '2': 'nba',
//     name: 'why',
//     age: 18,
//     address: '广州市'
//   }
  • 展开语法是浅拷贝
const info = {
  name: 'why',
  friend: { name: 'kobe' }
}

const obj = { ...info, name: 'coderwhy' }
// console.log(obj)
obj.friend.name = 'james'

console.log(info.friend.name) //james

8、数值表示

const num1 = 100 // 十进制
// b -> binary
const num2 = 0b100 // 二进制
// o -> octonary
const num3 = 0o100 // 八进制
// x -> hexadecimal
const num4 = 0x100 // 十六进制

console.log(num1, num2, num3, num4) //100 4 64 256

// 大的数值的连接符(ES2021 ES12),该写法方便阅读
const num = 10_000_000_000_000_000
console.log(num) //10000000000000000

9、Symbol的基本使用

  • 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突,比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下, 很容易造成冲突,从而覆盖掉它内部的某个属性;
  • Symbol是ES6中新增的一个基本数据类型,翻译为符号,用来生成一个独一无二的值,Symbol即使多次创建值,它们也是不同的。Symbol值是通过Symbol函数来生成的,生成后可以作为属性名也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值
  • 我们也可以在创建Symbol值的时候传入一个描述description,这个是ES2019(ES10)新增的特性。
// 1.ES6之前, 对象的属性名(key)
var obj = {
  name: 'why',
  friend: { name: 'kobe' },
  age: 18
}
obj['newName'] = 'james'
console.log(obj) //{ name: 'why', friend: { name: 'kobe' }, age: 18, newName: 'james' }

// 2.ES6中Symbol的基本使用
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2) //false

// ES2019(ES10)中, Symbol还有一个描述(description)
const s3 = Symbol('aaa')
console.log(s3.description) //aaa

// 3.Symbol值作为key
// 3.1.在定义对象字面量时使用
const obj2 = {
  [s1]: 'abc',
  [s2]: 'cba'
}

// 3.2.新增属性
obj2[s3] = 'nba'

// 3.3.Object.defineProperty方式
const s4 = Symbol()
Object.defineProperty(obj2, s4, {
  enumerable: true,
  configurable: true,
  writable: true,
  value: 'mba'
})

console.log(obj2[s1], obj2[s2], obj2[s3], obj2[s4]) //abc cba nba mba
// 注意: 不能通过.语法获取
console.log(obj2.s1) //undefined

// 4.使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值
// 需要Object.getOwnPropertySymbols来获取所有Symbol的key
console.log(Object.keys(obj2)) //[]
console.log(Object.getOwnPropertyNames(obj2)) //[]
console.log(Object.getOwnPropertySymbols(obj2)) //[ Symbol(), Symbol(), Symbol(aaa), Symbol() ]
const sKeys = Object.getOwnPropertySymbols(obj2)
for (const sKey of sKeys) {
  console.log(obj2[sKey])
  // abc
  // cba
  // nba
  // mba
}

// 5.Symbol.for(key)/Symbol.keyFor(symbol)
const sa = Symbol.for('aaa')
const sb = Symbol.for('aaa')
console.log(sa === sb) //true

const key = Symbol.keyFor(sa)
console.log(key) //aaa
const sc = Symbol.for(key)
console.log(sa === sc) //true

10、Set

在ES6之前,我们存储数据的结构主要有两种:数组、对象,在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复(那么Set有一个非常常用的功能就是给数组去重)。创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式)。

  • Set常见的属性:

    • size:返回Set中元素的个数;
  • Set常用的方法:
    • add(value):添加某个元素,返回Set对象本身;
    • delete(value):从set中删除和这个值相等的元素,返回boolean类型;
    • has(value):判断set中是否存在某个元素,返回boolean类型;
    • clear():清空set中所有的元素,没有返回值;
    • forEach(callback, [, thisArg]):通过forEach遍历set;
  • 另外Set是支持for...of的遍历的。
  • 基本使用
// 1.创建Set结构
var set = new Set()
set.add(2)
set.add(2)
set.add(30)
set.add(40)
set.add(2)
set.add(230)
console.log(set) //Set(4) { 2, 30, 40, 230 }

// 2.添加对象时特别注意:
// 这是两个不同的变量
set.add({})
set.add({})
console.log(set) //Set(6) { 2, 30, 40, 230, {}, {} }

// obj存储的是地址,set存储的元素不重复
const obj = {}
set.add(obj)
set.add(obj)
console.log(set) //Set(7) { 2, 30, 40, 230, {}, {}, {} }

// 3.对数组去重(去除重复的元素)
const arr = [43, 10, 26, 30, 43, 26, 10]
// 3.1第一种方法
// const newArr = []
// for (const item of arr) {
//   if (newArr.indexOf(item) !== -1) {
//     newArr.push(item)
//   }
// }

// 3.2第二种方法
const arrSet = new Set(arr)
// const newArr = Array.from(arrSet)
const newArr = [...arrSet]
console.log(newArr) //[ 43, 10, 26, 30 ]

// 4.size属性
console.log(arrSet.size) //4

// 5.Set的方法
// add
arrSet.add(1000)
console.log(arrSet) //Set(5) { 43, 10, 26, 30, 1000 }

// delete
arrSet.delete(43)
console.log(arrSet) //Set(4) { 10, 26, 30, 1000 }

// has
console.log(arrSet.has(100)) //false

// clear
// arrSet.clear()
console.log(arrSet) //Set(0) {}

// 6.对Set进行遍历
arrSet.forEach(item => {
  console.log(item)
  //   10
  //   26
  //   30
  //   1000
})

for (const item of arrSet) {
  console.log(item)
  //   10
  //   26
  //   30
  //   1000
}

11、WeakSet

和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。

  • 那么和Set有什么区别呢?

    • 区别一:WeakSet中只能存放对象类型不能存放基本数据类型
    • 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收
  • WeakSet常见的方法:
    • add(value):添加某个元素,返回WeakSet对象本身;
    • delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
    • has(value):判断WeakSet中是否存在某个元素,返回boolean类型。
const weakSet = new WeakSet()

// 1.区别一: 只能存放对象类型
// TypeError: Invalid value used in weak set
// weakSet.add(10)

// 2.区别二: 对对象是一个弱引用
let obj = {
  name: 'why'
}

const set = new Set()
// 建立的是强引用
set.add(obj)

// 建立的是弱引用
weakSet.add(obj)
console.log(weakSet)// WeakSet { <items unknown> }

// 3.WeakSet的应用场景
const personSet = new WeakSet()
class Person {
  constructor() {
    personSet.add(this)
  }

  running() {
    if (!personSet.has(this)) {
      throw new Error('不能通过非构造方法创建出来的对象调用running方法')
    }
    console.log('running~', this) //running~ Person {}
  }
}

let p = new Person()
p.running()

// 抛出异常
// p.running.call({ name: 'why' })

如果obj=null,虽然0xa00对象还有引用。但是由于是弱引用,GC还是会回收0xa00对象。

12、Map

  • 新增的数据结构是Map,用于存储映射关系,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?

    • 事实上我们对象存储映射关系只能用 字符串(ES6新增了Symbol) 作为属性名(key);
    • 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;
  • Map常见的属性:
    • size:返回Map中元素的个数;
  • Map常见的方法:
    • set(key, value):在Map中添加key、value,并且返回整个Map对象;
    • get(key):根据key获取Map中的value;
    • has(key):判断是否包括某一个key,返回Boolean类型;
    • delete(key):根据key删除一个键值对,返回Boolean类型;
    • clear():清空所有的元素;
    • forEach(callback, [, thisArg]):通过forEach遍历Map;
  • Map也可以通过for of进行遍历。
// 1.JavaScript中对象中是不能使用对象来作为key的
const obj1 = { name: 'why' }
const obj2 = { name: 'kobe' }

const info = {
  [obj1]: 'aaa',
  [obj2]: 'bbb'
}

console.log(info) //{ '[object Object]': 'bbb' }

// 2.Map就是允许我们对象类型来作为key的
// 构造方法的使用
const map = new Map()
map.set(obj1, 'aaa')
map.set(obj2, 'bbb')
map.set(1, 'ccc')
console.log(map)
// Map(3) {
//     { name: 'why' } => 'aaa',
//     { name: 'kobe' } => 'bbb',
//     1 => 'ccc'
//  }

const map2 = new Map([
  [obj1, 'aaa'],
  [obj2, 'bbb'],
  [2, 'ddd']
])
console.log(map2)
// Map(3) {
//     { name: 'why' } => 'aaa',
//     { name: 'kobe' } => 'bbb',
//     2 => 'ccc'
//  }

// 3.常见的属性和方法
console.log(map2.size) //3

// set
map2.set('why', 'eee')
console.log(map2)
// Map(4) {
//     { name: 'why' } => 'aaa',
//     { name: 'kobe' } => 'bbb',
//     2 => 'ddd',
//     'why' => 'eee'
//  }

// get(key)
console.log(map2.get('why')) //eee

// has(key)
console.log(map2.has('why')) //true

// delete(key)
map2.delete('why')
console.log(map2)
// Map(3) {
//     { name: 'why' } => 'aaa',
//     { name: 'kobe' } => 'bbb',
//     2 => 'ddd'
// }

// clear(),全部清空
// map2.clear()
// console.log(map2)

// 4.遍历map
map2.forEach((item, key) => {
  console.log(item, key)
  // aaa { name: 'why' }
  // bbb { name: 'kobe' }
  // ddd 2
})

for (const item of map2) {
  console.log(item[0], item[1])
  // { name: 'why' } aaa
  // { name: 'kobe' } bbb
  // 2 ddd
}

for (const [key, value] of map2) {
  console.log(key, value)
  // { name: 'why' } aaa
  // { name: 'kobe' } bbb
  // 2 ddd
}

13、WeakMap

和Map类型的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。

  • 那么和Map有什么区别呢?

    • 区别一:WeakMap的key只能使用对象,不接受其他的类型作为key;
    • 区别二:WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;
  • WeakMap常见的方法有四个:
    • set(key, value):在Map中添加key、value,并且返回整个Map对象;
    • get(key):根据key获取Map中的value;
    • has(key):判断是否包括某一个key,返回Boolean类型;
    • delete(key):根据key删除一个键值对,返回Boolean类型;
const obj = {name: "obj1"}
// 1.WeakMap和Map的区别二:弱引用
const map = new Map()
map.set(obj, "aaa")

const weakMap = new WeakMap()
weakMap.set(obj, "aaa")

// 2.区别一: 不能使用基本数据类型
// weakMap.set(1, "ccc")

// 3.常见方法
// get方法
console.log(weakMap.get(obj))//aaa

// has方法
console.log(weakMap.has(obj))//true

// delete方法
console.log(weakMap.delete(obj))//true
// WeakMap { <items unknown> }
console.log(weakMap)//WeakMap { <items unknown> }
  • 使用场景:响应式原理中的WeakMap的使用(简单实现)
// 应用场景(vue3响应式原理)
const obj1 = {
  name: 'why',
  age: 18
}

function obj1NameFn1() {
  console.log('obj1NameFn1被执行')
}

function obj1NameFn2() {
  console.log('obj1NameFn2被执行')
}

function obj1AgeFn1() {
  console.log('obj1AgeFn1')
}

function obj1AgeFn2() {
  console.log('obj1AgeFn2')
}

const obj2 = {
  name: 'kobe',
  height: 1.88,
  address: '广州市'
}

function obj2NameFn1() {
  console.log('obj1NameFn1被执行')
}

function obj2NameFn2() {
  console.log('obj1NameFn2被执行')
}

// 1.创建WeakMap
const weakMap = new WeakMap()

// 2.收集依赖结构
// 2.1.对obj1收集的数据结构
const obj1Map = new Map()
obj1Map.set('name', [obj1NameFn1, obj1NameFn2])
obj1Map.set('age', [obj1AgeFn1, obj1AgeFn2])
weakMap.set(obj1, obj1Map)

// 2.2.对obj2收集的数据结构
const obj2Map = new Map()
obj2Map.set('name', [obj2NameFn1, obj2NameFn2])
weakMap.set(obj2, obj2Map)

// 3.如果obj1.name发生了改变
// Proxy/Object.defineProperty
obj1.name = 'james'
const targetMap = weakMap.get(obj1)
const fns = targetMap.get('name')
fns.forEach(item => item())
// obj1NameFn1被执行
// obj1NameFn2被执行

总结

到此这篇关于ES6中常见基本知识点的基本使用实的文章就介绍到这了,更多相关ES6常见知识点内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 关于ES6新特性最常用的知识点汇总

    目录 1.关键字 2.解构 3.字符串 4.正则 5.数组 6.函数 7.对象 8.Symbol 9.集合 10.Proxy配合Reflect的观察者模式 11. Promise 12.遍历器 13.Generator 14.async 15.Class 16.修饰器 17.Moudle 总结 1.关键字 Let 关键字 在let所在的代码块中起作用.在let之前对于改该变量是不能进行赋值的 Const关键字  为只读变量,因此在定义的时候就需要去赋值. 2.解构 变量的解构, 1>.数组结构利

  • ES6知识点整理之数组解构和字符串解构的应用示例

    本文实例讲述了ES6知识点整理之数组解构和字符串解构的应用.分享给大家供大家参考,具体如下: ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring), 而数组的解构赋值是从数组中提取值,按照对应位置,对变量赋值. ES6之前的赋值操作 var arr = [1,2,3]; var a = arr[0]; var b = arr[1]; var c = arr[2]; console.log(a,b,c); // 1 2 3 对一维数组的解构赋值

  • ES6知识点整理之模块化的应用详解

    本文实例讲述了ES6知识点整理之模块化的应用.分享给大家供大家参考,具体如下: 目前浏览器还不能完全支持模块化,需要引入很多编译环境,下面在nodejs中来模拟ES6中的模块化 nodejs中针对模块化演示的配置 环境的安装:$ npm install --save babel-cli babel-preset-node6 运行:$ ./node_modules/.bin/babel-node.js --presets node6 ./your_script.js 添加.babelrc文件, 编

  • ES6学习笔记之字符串、数组、对象、函数新增知识点实例分析

    本文实例讲述了ES6学习笔记之字符串.数组.对象.函数新增知识点.分享给大家供大家参考,具体如下: 1.模板字符串 反引号`` 内用于输入格式化的字符串文本,在``内可以将表达式用${}包含起来 let str=` <!DOCTYPE html> <html lang="en"> <body> <div> <p class="pClass">格式化字符串</p> </div> <

  • ES6知识点整理之函数数组参数的默认值及其解构应用示例

    本文实例讲述了ES6知识点整理之函数数组参数的默认值及其解构应用.分享给大家供大家参考,具体如下: 在ES6中, 函数的参数也可以使用解构赋值和默认值的设置,下面我们来看下 在ES6之前设置函数默认值的写法 function test(x,y) { x = x || 12; y = y || 22; console.log(x,y); } test(); // 12 22 test(1,2) // 1 2 在ES6中给函数参数赋默认值 function test(x=12, y=22) { co

  • ES6知识点整理之对象解构赋值应用示例

    本文实例讲述了ES6知识点整理之对象解构赋值应用.分享给大家供大家参考,具体如下: ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring), 在对象的解构赋值中有一些需要注意的事项 初识对象的解构 var {name} = { name:'Joh', age:10 }; console.log(name); // Joh 通过解构的形式取出对象中的属性值 对解构出的属性进行重命名 var {name} = { name:'Joh', age:1

  • ES6知识点整理之Proxy的应用实例详解

    本文实例讲述了ES6知识点整理之Proxy的应用.分享给大家供大家参考,具体如下: Proxy 用于修改对象某些操作的默认行为,可以对外界的访问进行过滤和改写,其概念类似于元编程. Proxy 让我们可以对任何对象的绝大部分行为进行监听和干涉,实现更多的自定义程序行为.在目标对象之前架设一层"拦截",外界对该对象的访问,都必须先通过这层拦截. 目前[兼容性]存在一定的问题,目前在chrome和ff浏览器中的非严格模式下可用,一些先进的技术即使在目前不能广泛应用,但随着时间的流逝,都将会

  • ES6知识点整理之String字符串新增常用方法示例

    本文实例讲述了ES6知识点整理之String字符串新增常用方法.分享给大家供大家参考,具体如下: 字符串includes,startsWith,endsWith方法测试 普通的用法: <script> var str = 'Hello'; console.log(str.indexOf('o')); // 4 console.log(str.includes('e')); // true console.log(str.startsWith('H')); // true console.log

  • ES6知识点整理之函数对象参数默认值及其解构应用示例

    本文实例讲述了ES6知识点整理之函数对象参数默认值及其解构应用.分享给大家供大家参考,具体如下: 同函数数组参数一样,函数的对象参数的默认值和解构过程整理 函数对象参数的默认值与解构的形式 此处使用箭头函数来处理 : (({x,y})=>{ console.log(x, y); // // undefined undefined })({}); (({x=1,y=2})=>{ console.log(x,y); // 1 2 })({}); (({x=3, y=4}={})=>{ con

  • ES6中常见基本知识点的基本使用实例汇总

    目录 前言 1.字面量的增强 2.解构Destructuring 3.let和const 4.作用域 5.模板子符串 6.函数 7.展开语法 8.数值表示 9.Symbol的基本使用 10.Set 11.WeakSet 12.Map 13.WeakMap 总结 前言 学习了coderwhy的JavaScript高级语法视频课的笔记 如有错误或者不合适的地方,敬请见谅,欢迎指出和拓展,谢谢各位了 1.字面量的增强 var name = 'xxx' var age = 12 var obj = {

  • JavaScript中常见的字符串操作函数及用法汇总

    本文实例总结了JavaScript中常见的字符串操作函数及用法.分享给大家供大家参考.具体分析如下: 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信你也跟我一样,发现字符串的处理是前端招聘过程中最常见的题型之一.这些题有一个特点,站在考官的角度去考虑,它考的不是你会不会,而是你能不能在不借用XX手册或者XX指南再或者百度谷歌的情况下,用比较简洁的方式写出答案来.可惜的是,很多开发人员,当然我也

  • es6中Promise 对象基本功能与用法实例分析

    本文实例讲述了es6中Promise 对象基本功能与用法.分享给大家供大家参考,具体如下: Promise 是异步编程的一种解决方案,解决--回调函数和事件 ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. 下面代码创造了一个Promise实例. 基本用法 ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. const promise = new Promise(function(resolve, reject) { //resolve (d

  • python中os操作文件及文件路径实例汇总

    本文实例讲述了python中os操作文件及文件路径的方法.分享给大家供大家参考.具体分析如下: python获取文件上一级目录:取文件所在目录的上一级目录 复制代码 代码如下: os.path.abspath(os.path.join(os.path.dirname('settings.py'),os.path.pardir)) os.path.pardir是父目录,os.path.abspath是绝对路径 举例具体看一下输出: 复制代码 代码如下: print os.path.dirname(

  • ES6中新增的Object.assign()方法详解

    前言 将A对象的属性复制给B对象,这是JavaScript编程中很常见的操作.下面这篇文章将介绍ES6的Object.assign()属性,可以用于对象复制. 在JavaScript生态系统中,对象复制有另外一个术语: extend.下面是两个JS库提供的extend接口: Prototype: Object.extend(destination, source) Underscore.js: _.extend(destination, *sources) Object.assign()介绍 E

  • es6中的解构赋值、扩展运算符和rest参数使用详解

    前言 本文主要给大家介绍了关于es6中解构赋值.扩展运算符和rest参数使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. es6中较为常用的书写风格 为了书写的方便,es6中提出了很多比较友好的书写方式,其中最为常见的属于以下几个: 字符串模板 `abcdef${test}` 解构赋值 let [a, b, c] = [1, 2, 3] 扩展运算符 rest参数 ... 本文希望能够学习其中的主要的用法,方便书写和简洁性. 字符串模板 在以前的日子,我们经常捡到各

  • 详解JavaScript ES6中的Generator

    今天讨论的新特性让我非常兴奋,因为这个特性是 ES6 中最神奇的特性. 这里的"神奇"意味着什么呢?对于初学者来说,该特性与以往的 JS 完全不同,甚至有些晦涩难懂.从某种意义上说,它完全改变了这门语言的通常行为,这不是"神奇"是什么呢. 不仅如此,该特性还可以简化程序代码,将复杂的"回调堆栈"改成直线执行的形式. 我是不是铺垫的太多了?下面开始深入介绍,你自己去判断吧. 简介 什么是 Generator? 看下面代码: function* qu

  • 老生常谈ES6中的类

    前面的话 大多数面向对象的编程语言都支持类和类继承的特性,而JS却不支持这些特性,只能通过其他方法定义并关联多个相似的对象,这种状态一直延续到了ES5.由于类似的库层出不穷,最终还是在ECMAScript 6中引入了类的特性.本文将详细介绍ES6中的类 ES5近似结构 在ES5中没有类的概念,最相近的思路是创建一个自定义类型:首先创建一个构造函数,然后定义另一个方法并赋值给构造函数的原型 function PersonType(name) { this.name = name; } Person

  • 解读ES6中class关键字

    class是es6引入的最重要特性之一.在没有class之前,我们只能通过原型链来模拟类. 1 .介绍  //定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } Point类除了构造方法,还定义了一个toString方法.注意,定义"类"的方法的时候,前面不需要加上function这个关键字,

  • ES6中Symbol、Set和Map用法详解

    本文实例讲述了ES6中Symbol.Set和Map用法.分享给大家供大家参考,具体如下: Symbol 1.Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值.它是 JavaScript 语言的第七种数据类型,前六种分别是:undefined.null.布尔值(Boolean).字符串(String).数值(Number).对象(Object): 2.Symbol 值通过Symbol函数生成,可以作为对象的属性名使用,保证不会与其他属性名产生冲突: let s = Symbo

随机推荐