欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ES6中常見(jiàn)基本知識(shí)點(diǎn)的基本使用實(shí)例匯總

 更新時(shí)間:2022年04月01日 09:49:09   作者:一個(gè)默默無(wú)聞的小白  
這篇文章主要給大家介紹了關(guān)于ES6中常見(jiàn)基本知識(shí)點(diǎn)的基本使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前言

學(xué)習(xí)了coderwhy的JavaScript高級(jí)語(yǔ)法視頻課的筆記

如有錯(cuò)誤或者不合適的地方,敬請(qǐng)見(jiàn)諒,歡迎指出和拓展,謝謝各位了

1、字面量的增強(qiáng)

var name = 'xxx'
var age = 12
var obj = {
  // 1.property shorthand(屬性的簡(jiǎn)寫(xiě))
  name: name,
  age,

  // 2.method shorthand(方法的簡(jiǎn)寫(xiě))
  foo: function () {
    console.log(1)
  },

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

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

  // 3.computed property name(計(jì)算屬性名)
  [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、解構(gòu)Destructuring

  • 數(shù)組解構(gòu)
var arr = ['aaa', 'bbb', 'ccc']
// 以前的做法
// var a1 = arr[0]
// var a2 = arr[1]
// var a3 = arr[2]

// 1、對(duì)數(shù)組的解構(gòu)
var [a1, a2, a3] = arr
console.log(a1, a2, a3) //aaa bbb ccc

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

// 3、解構(gòu)出一個(gè)元素,后面的元素放到一個(gè)新數(shù)組中
var [a5, ...newArr] = arr
console.log(a5, newArr) //aaa [ 'bbb', 'ccc' ]

// 4、解構(gòu)的默認(rèn)值
var [a6, a7, a8, a9 = 'ddd'] = arr
console.log(a6, a7, a8, a9) //aaa bbb ccc ddd
  • 對(duì)象解構(gòu)
var obj = {
  name: 'xxx',
  age: 123,
  address: '廣東'
}

//1、全部解構(gòu)
var { name, age, address } = obj
console.log(name, age, address) //xxx 123 廣東

//2、解構(gòu)單個(gè)
var { age } = obj
console.log(age) //123

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

//4、解構(gòu)的默認(rèn)值
var { color: newColor = 'red' } = obj
console.log(newColor) //red

//5、函數(shù)中
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

  • 基本語(yǔ)法
// 1、從直觀的角度來(lái)說(shuō),let和var是沒(méi)有太大的區(qū)別的,都是用于聲明一個(gè)變量
let bar = "bar"

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

// 3、
// 注意事項(xiàng)一: const本質(zhì)上是傳遞的值不可以修改
// 但是如果傳遞的是一個(gè)引用類(lèi)型(內(nèi)存地址), 可以通過(guò)引用找到對(duì)應(yīng)的對(duì)象, 去修改對(duì)象內(nèi)部的屬性, 這個(gè)是可以的
const obj = {
    foo: "foo"
}

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

// 4、
// 注意事項(xiàng)二: 通過(guò)let/const定義的變量名是不可以重復(fù)定義
// let foo = "abc"
// let foo = "cba"
  • 作用域提升
  • 在執(zhí)行上下文的詞法環(huán)境創(chuàng)建出來(lái)的時(shí)候,變量事實(shí)上已經(jīng)被創(chuàng)建了,只是這個(gè)變量是不能被提前訪問(wèn)的。

  • 那么我們自己從字面量上理解:在聲明變量的作用域中,如果這個(gè)變量可以在聲明之前被訪問(wèn),那么我們可以稱(chēng)之為作用域提升。

// 作用域提升: 能提前被訪問(wèn)
console.log(foo)// undefined
var foo = "foo"

// let/const他們是沒(méi)有作用域提升
// foo被創(chuàng)建出來(lái)了, 但是不能被訪問(wèn)
// Reference(引用)Error: Cannot access 'foo' before initialization(初始化)
console.log(foo)
let foo = "foo"
  • let、const和window的關(guān)系
  • 我們知道,在全局通過(guò)var來(lái)聲明一個(gè)變量,事實(shí)上會(huì)在window上添加一個(gè)屬性,但是let、const是不會(huì)給window上添加任何屬性。
  • 基于早期ECMA的版本規(guī)范:
    • 每一個(gè)執(zhí)行上下文會(huì)被關(guān)聯(lián)到一個(gè)變量對(duì)象(variable object,VO),在源代碼中的變量和函數(shù)聲明會(huì)被作為屬性添加到VO中。對(duì)與函數(shù)來(lái)說(shuō),參數(shù)也會(huì)被添加到VO中。
  • 在最新的ECMA的版本規(guī)范中,對(duì)于一些詞匯進(jìn)行了修改:
    • 每一個(gè)執(zhí)行上下文會(huì)被關(guān)聯(lián)到一個(gè)變量環(huán)境(VariableEnvironment,VE),在執(zhí)行代碼中的變量和函數(shù)聲明會(huì)被作為環(huán)境記錄(Environment Record)添加到變量環(huán)境中。對(duì)與函數(shù)來(lái)說(shuō),參數(shù)也會(huì)被環(huán)境記錄添加到變量環(huán)境中。

也就是說(shuō)我們聲明的變量和環(huán)境記錄是被添加到變量環(huán)境中的,但是標(biāo)準(zhǔn)沒(méi)有規(guī)定這個(gè)對(duì)象是window對(duì)象或者其他對(duì)象,那么JS引擎在解析的時(shí)候,其實(shí)會(huì)有自己的實(shí)現(xiàn)。比如v8中其實(shí)是通過(guò)VariableMap的一個(gè)hashmap來(lái)實(shí)現(xiàn)它們的存儲(chǔ)的(VE->variables_)。

那么window對(duì)象呢?而window對(duì)象是早期的GO對(duì)象,在最新的實(shí)現(xiàn)中其實(shí)是瀏覽器添加的全局對(duì)象,并且 一直保持了window和var之間值的相等性。

var a = 123
let b = 456

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

4、作用域

  • ES5作用域(ES5中沒(méi)有塊級(jí)作用域)
// 在ES5中只有兩個(gè)東西會(huì)形成作用域
// 1.全局作用域

// 2.函數(shù)(局部)作用域
function foo() {
    var bar = "bar"
}
  • ES6作用域(新增一個(gè)塊級(jí)作用域)
// ES6的代碼塊級(jí)作用域
// 對(duì)let/const/function/class聲明的類(lèi)型是有效
{
  let foo = 'why'
  function demo() {
    console.log('demo function')
  }
  class Person {}
}

console.log(foo) // foo is not defined
// 不同的瀏覽器有不同實(shí)現(xiàn)的(大部分瀏覽器為了兼容以前的代碼, 讓function是沒(méi)有塊級(jí)作用域)
demo() //demo function
var p = new Person() // Person is not defined
// 1、if語(yǔ)句的代碼就是塊級(jí)作用域
if (true) {
  var foo = 'foo'
  let bar = 'bar'
}

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

// 2、switch語(yǔ)句的代碼也是塊級(jí)作用域
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語(yǔ)句的代碼也是塊級(jí)作用域
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
  • 塊級(jí)作用域的應(yīng)用場(chǎng)景

點(diǎn)擊不同的button打印出不同的button編號(hào)的兩種實(shí)現(xiàn)方法。

const btns = document.getElementsByTagName('button')
// 1、var沒(méi)有塊級(jí)作用域
for (var i = 0; i < btns.length; i++) {
  ;(function (n) {
    btns[i].onclick = function () {
      console.log('第' + n + '個(gè)按鈕被點(diǎn)擊')
    }
  })(i)
}

// 2、let有塊級(jí)作用域
for (let i = 0; i < btns.length; i++) {
  btns[i].onclick = function () {
    console.log('第' + i + '個(gè)按鈕被點(diǎn)擊')
  }
}
  • 塊級(jí)作用域的補(bǔ)充
const names = ['abc', 'cba', 'nba']

// 1、不可以使用const,因?yàn)閕的每次循環(huán)(生成一個(gè)塊級(jí)作用域)都不一樣,其實(shí)都是需要上一次的i進(jìn)行i++賦值給下一個(gè)i
for (let i = 0; i < names.length; i++) {
  console.log(names[i])
}

// 2、for...of: ES6新增的遍歷數(shù)組(對(duì)象)
// 因?yàn)槊看伪闅v(生成一個(gè)塊級(jí)作用域)的值都賦給一個(gè)item,所以不需要上一次item的值進(jìn)行操作
for (const item of names) {
  console.log(item)
}
  • let和const的暫時(shí)性死區(qū)

在ES6中,我們還有一個(gè)概念稱(chēng)之為暫時(shí)性死區(qū):它表達(dá)的意思是在一個(gè)代碼中,使用let、const聲明的變量,在聲明之前,變量都是不可以訪問(wèn)的,我們將這種現(xiàn)象稱(chēng)之為 temporal dead zone(暫時(shí)性死區(qū),TDZ)。

var foo = 'foo'

// 塊級(jí)作用域
if (true) {
  console.log(foo) //Cannot access 'foo' before initialization

  let foo = 'abc'
}
  • var、let、const的選擇
  • 對(duì)于var的使用:
    • 我們需要明白一個(gè)事實(shí),var所表現(xiàn)出來(lái)的特殊性:比如作用域提升、window全局對(duì)象、沒(méi)有塊級(jí)作用域等都是一些 歷史遺留問(wèn)題;
    • 其實(shí)是JavaScript在設(shè)計(jì)之初的一種語(yǔ)言缺陷;
  • 對(duì)于let、const:
    • 對(duì)于let和const來(lái)說(shuō),是目前開(kāi)發(fā)中推薦使用的;
    • 我們會(huì)優(yōu)先推薦使用const,這樣可以保證數(shù)據(jù)的安全性不會(huì)被隨意的篡改;
    • 只有當(dāng)我們明確知道一個(gè)變量后續(xù)會(huì)需要被重新賦值時(shí),這個(gè)時(shí)候再使用let;
    • 這種在很多其他語(yǔ)言里面也都是一種約定俗成的規(guī)范,盡量我們也遵守這種規(guī)范;

5、模板子符串

  • 基本使用
// ES6之前拼接字符串和其他標(biāo)識(shí)符
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)
  • 標(biāo)簽?zāi)0遄址?/li>
// 第一個(gè)參數(shù)依然是模塊字符串中整個(gè)字符串, 只是被切成多塊,放到了一個(gè)數(shù)組中
// 第二個(gè)參數(shù)是模塊字符串中, 第一個(gè) ${}
function foo(m, n, x) {
  console.log(m, n, x)
}

// 另外調(diào)用函數(shù)的方式: 標(biāo)簽?zāi)K字符串
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、函數(shù)

  • 函數(shù)的默認(rèn)參數(shù)
// 1.ES6可以給函數(shù)參數(shù)提供默認(rèn)值
function foo(m = 'aaa', n = 'bbb') {
  console.log(m, n)
}

foo(0)// 0 bbb

// 2.對(duì)象參數(shù)和默認(rèn)值以及解構(gòu)
function printInfo({ name, age } = { name: 'why', age: 18 }) {
  console.log(name, age)
}
printInfo({ name: 'kobe', age: 40 }) //kobe 40

// 另外一種寫(xiě)法
function printInfo1({ name = 'why', age = 18 } = {}) {
  console.log(name, age)
}
printInfo1() //why 18

// 3.有默認(rèn)值的形參最好放到最后
function bar(x, y, z = 30) {
  console.log(x, y, z)
}

bar(10, 20) //10 20 30

// 4.有默認(rèn)值的函數(shù)的length屬性
function baz(x, y, z, m, n = 30) {
  console.log(x, y, z, m, n)
}

console.log(baz.length)// 4
  • 函數(shù)的剩余次數(shù)
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
  • 箭頭函數(shù)

箭頭函數(shù)是沒(méi)有顯式原型的,所以不能作為構(gòu)造函數(shù),使用new來(lái)創(chuàng)建對(duì)象。

function foo() {}

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

var bar = () => {
  console.log(this, arguments) //箭頭函數(shù)本身沒(méi)有
}

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

7、展開(kāi)語(yǔ)法

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

// 1.函數(shù)調(diào)用時(shí)
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.構(gòu)造數(shù)組時(shí)
const newNames = [...names, ...name]
console.log(newNames) //[ 'abc', 'cba', 'nba', 'w', 'h', 'y' ]

// 3.構(gòu)建對(duì)象字面量時(shí)ES2018(ES9)
const obj = { ...info, address: '廣州市', ...names }
console.log(obj)
// {
//     '0': 'abc',
//     '1': 'cba',
//     '2': 'nba',
//     name: 'why',
//     age: 18,
//     address: '廣州市'
//   }
  • 展開(kāi)語(yǔ)法是淺拷貝
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、數(shù)值表示

const num1 = 100 // 十進(jìn)制
// b -> binary
const num2 = 0b100 // 二進(jìn)制
// o -> octonary
const num3 = 0o100 // 八進(jìn)制
// x -> hexadecimal
const num4 = 0x100 // 十六進(jìn)制

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

// 大的數(shù)值的連接符(ES2021 ES12),該寫(xiě)法方便閱讀
const num = 10_000_000_000_000_000
console.log(num) //10000000000000000

9、Symbol的基本使用

  • 在ES6之前,對(duì)象的屬性名都是字符串形式,那么很容易造成屬性名的沖突,比如原來(lái)有一個(gè)對(duì)象,我們希望在其中添加一個(gè)新的屬性和值,但是我們?cè)诓淮_定它原來(lái)內(nèi)部有什么內(nèi)容的情況下, 很容易造成沖突,從而覆蓋掉它內(nèi)部的某個(gè)屬性;
  • Symbol是ES6中新增的一個(gè)基本數(shù)據(jù)類(lèi)型,翻譯為符號(hào),用來(lái)生成一個(gè)獨(dú)一無(wú)二的值,Symbol即使多次創(chuàng)建值,它們也是不同的。Symbol值是通過(guò)Symbol函數(shù)來(lái)生成的,生成后可以作為屬性名也就是在ES6中,對(duì)象的屬性名可以使用字符串,也可以使用Symbol值;
  • 我們也可以在創(chuàng)建Symbol值的時(shí)候傳入一個(gè)描述description,這個(gè)是ES2019(ES10)新增的特性。
// 1.ES6之前, 對(duì)象的屬性名(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還有一個(gè)描述(description)
const s3 = Symbol('aaa')
console.log(s3.description) //aaa

// 3.Symbol值作為key
// 3.1.在定義對(duì)象字面量時(shí)使用
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
// 注意: 不能通過(guò).語(yǔ)法獲取
console.log(obj2.s1) //undefined

// 4.使用Symbol作為key的屬性名,在遍歷/Object.keys等中是獲取不到這些Symbol值
// 需要Object.getOwnPropertySymbols來(lái)獲取所有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之前,我們存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)主要有兩種:數(shù)組、對(duì)象,在ES6中新增了另外兩種數(shù)據(jù)結(jié)構(gòu):Set、Map,以及它們的另外形式WeakSet、WeakMap。Set是一個(gè)新增的數(shù)據(jù)結(jié)構(gòu),可以用來(lái)保存數(shù)據(jù),類(lèi)似于數(shù)組,但是和數(shù)組的區(qū)別是元素不能重復(fù)(那么Set有一個(gè)非常常用的功能就是給數(shù)組去重)。創(chuàng)建Set我們需要通過(guò)Set構(gòu)造函數(shù)(暫時(shí)沒(méi)有字面量創(chuàng)建的方式)。

  • Set常見(jiàn)的屬性:
    • size:返回Set中元素的個(gè)數(shù);
  • Set常用的方法:
    • add(value):添加某個(gè)元素,返回Set對(duì)象本身;
    • delete(value):從set中刪除和這個(gè)值相等的元素,返回boolean類(lèi)型;
    • has(value):判斷set中是否存在某個(gè)元素,返回boolean類(lèi)型;
    • clear():清空set中所有的元素,沒(méi)有返回值;
    • forEach(callback, [, thisArg]):通過(guò)forEach遍歷set;
  • 另外Set是支持for...of的遍歷的。
  • 基本使用
// 1.創(chuàng)建Set結(jié)構(gòu)
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.添加對(duì)象時(shí)特別注意:
// 這是兩個(gè)不同的變量
set.add({})
set.add({})
console.log(set) //Set(6) { 2, 30, 40, 230, {}, {} }

// obj存儲(chǔ)的是地址,set存儲(chǔ)的元素不重復(fù)
const obj = {}
set.add(obj)
set.add(obj)
console.log(set) //Set(7) { 2, 30, 40, 230, {}, {}, {} }

// 3.對(duì)數(shù)組去重(去除重復(fù)的元素)
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.對(duì)Set進(jìn)行遍歷
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類(lèi)似的另外一個(gè)數(shù)據(jù)結(jié)構(gòu)稱(chēng)之為WeakSet,也是內(nèi)部元素不能重復(fù)的數(shù)據(jù)結(jié)構(gòu)。

  • 那么和Set有什么區(qū)別呢?
    • 區(qū)別一:WeakSet中只能存放對(duì)象類(lèi)型,不能存放基本數(shù)據(jù)類(lèi)型;
    • 區(qū)別二:WeakSet對(duì)元素的引用是弱引用,如果沒(méi)有其他引用對(duì)某個(gè)對(duì)象進(jìn)行引用,那么GC可以對(duì)該對(duì)象進(jìn)行回收;
  • WeakSet常見(jiàn)的方法:
    • add(value):添加某個(gè)元素,返回WeakSet對(duì)象本身;
    • delete(value):從WeakSet中刪除和這個(gè)值相等的元素,返回boolean類(lèi)型;
    • has(value):判斷WeakSet中是否存在某個(gè)元素,返回boolean類(lèi)型。
const weakSet = new WeakSet()

// 1.區(qū)別一: 只能存放對(duì)象類(lèi)型
// TypeError: Invalid value used in weak set
// weakSet.add(10)

// 2.區(qū)別二: 對(duì)對(duì)象是一個(gè)弱引用
let obj = {
  name: 'why'
}

const set = new Set()
// 建立的是強(qiáng)引用
set.add(obj)

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

// 3.WeakSet的應(yīng)用場(chǎng)景
const personSet = new WeakSet()
class Person {
  constructor() {
    personSet.add(this)
  }

  running() {
    if (!personSet.has(this)) {
      throw new Error('不能通過(guò)非構(gòu)造方法創(chuàng)建出來(lái)的對(duì)象調(diào)用running方法')
    }
    console.log('running~', this) //running~ Person {}
  }
}

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

// 拋出異常
// p.running.call({ name: 'why' })

如果obj=null,雖然0xa00對(duì)象還有引用。但是由于是弱引用,GC還是會(huì)回收0xa00對(duì)象。

12、Map

  • 新增的數(shù)據(jù)結(jié)構(gòu)是Map,用于存儲(chǔ)映射關(guān)系,在之前我們可以使用對(duì)象來(lái)存儲(chǔ)映射關(guān)系,他們有什么區(qū)別呢?
    • 事實(shí)上我們對(duì)象存儲(chǔ)映射關(guān)系只能用 字符串(ES6新增了Symbol) 作為屬性名(key);
    • 某些情況下我們可能希望通過(guò)其他類(lèi)型作為key,比如對(duì)象,這個(gè)時(shí)候會(huì)自動(dòng)將對(duì)象轉(zhuǎn)成字符串來(lái)作為key;
  • Map常見(jiàn)的屬性:
    • size:返回Map中元素的個(gè)數(shù);
  • Map常見(jiàn)的方法:
    • set(key, value):在Map中添加key、value,并且返回整個(gè)Map對(duì)象;
    • get(key):根據(jù)key獲取Map中的value;
    • has(key):判斷是否包括某一個(gè)key,返回Boolean類(lèi)型;
    • delete(key):根據(jù)key刪除一個(gè)鍵值對(duì),返回Boolean類(lèi)型;
    • clear():清空所有的元素;
    • forEach(callback, [, thisArg]):通過(guò)forEach遍歷Map;
  • Map也可以通過(guò)for of進(jìn)行遍歷。
// 1.JavaScript中對(duì)象中是不能使用對(duì)象來(lái)作為key的
const obj1 = { name: 'why' }
const obj2 = { name: 'kobe' }

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

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

// 2.Map就是允許我們對(duì)象類(lèi)型來(lái)作為key的
// 構(gòu)造方法的使用
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.常見(jiàn)的屬性和方法
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類(lèi)型的另外一個(gè)數(shù)據(jù)結(jié)構(gòu)稱(chēng)之為WeakMap,也是以鍵值對(duì)的形式存在的。

  • 那么和Map有什么區(qū)別呢?
    • 區(qū)別一:WeakMap的key只能使用對(duì)象,不接受其他的類(lèi)型作為key;
    • 區(qū)別二:WeakMap的key對(duì)對(duì)象想的引用是弱引用,如果沒(méi)有其他引用引用這個(gè)對(duì)象,那么GC可以回收該對(duì)象;
  • WeakMap常見(jiàn)的方法有四個(gè):
    • set(key, value):在Map中添加key、value,并且返回整個(gè)Map對(duì)象;
    • get(key):根據(jù)key獲取Map中的value;
    • has(key):判斷是否包括某一個(gè)key,返回Boolean類(lèi)型;
    • delete(key):根據(jù)key刪除一個(gè)鍵值對(duì),返回Boolean類(lèi)型;
const obj = {name: "obj1"}
// 1.WeakMap和Map的區(qū)別二:弱引用
const map = new Map()
map.set(obj, "aaa")

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

// 2.區(qū)別一: 不能使用基本數(shù)據(jù)類(lèi)型
// weakMap.set(1, "ccc")

// 3.常見(jiàn)方法
// 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> }
  • 使用場(chǎng)景:響應(yīng)式原理中的WeakMap的使用(簡(jiǎn)單實(shí)現(xiàn))
// 應(yīng)用場(chǎng)景(vue3響應(yīng)式原理)
const obj1 = {
  name: 'why',
  age: 18
}

function obj1NameFn1() {
  console.log('obj1NameFn1被執(zhí)行')
}

function obj1NameFn2() {
  console.log('obj1NameFn2被執(zhí)行')
}

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

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

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

function obj2NameFn1() {
  console.log('obj1NameFn1被執(zhí)行')
}

function obj2NameFn2() {
  console.log('obj1NameFn2被執(zhí)行')
}

// 1.創(chuàng)建WeakMap
const weakMap = new WeakMap()

// 2.收集依賴結(jié)構(gòu)
// 2.1.對(duì)obj1收集的數(shù)據(jù)結(jié)構(gòu)
const obj1Map = new Map()
obj1Map.set('name', [obj1NameFn1, obj1NameFn2])
obj1Map.set('age', [obj1AgeFn1, obj1AgeFn2])
weakMap.set(obj1, obj1Map)

// 2.2.對(duì)obj2收集的數(shù)據(jù)結(jié)構(gòu)
const obj2Map = new Map()
obj2Map.set('name', [obj2NameFn1, obj2NameFn2])
weakMap.set(obj2, obj2Map)

// 3.如果obj1.name發(fā)生了改變
// Proxy/Object.defineProperty
obj1.name = 'james'
const targetMap = weakMap.get(obj1)
const fns = targetMap.get('name')
fns.forEach(item => item())
// obj1NameFn1被執(zhí)行
// obj1NameFn2被執(zhí)行

總結(jié)

到此這篇關(guān)于ES6中常見(jiàn)基本知識(shí)點(diǎn)的基本使用實(shí)的文章就介紹到這了,更多相關(guān)ES6常見(jiàn)知識(shí)點(diǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript中0、空字符串、''0''是true還是false的知識(shí)點(diǎn)分享

    JavaScript中0、空字符串、''0''是true還是false的知識(shí)點(diǎn)分享

    在本篇文章里小編給大家整理的是JavaScript中0、空字符串、'0'是true還是false的知識(shí)點(diǎn)分享,有需要的朋友們參考下。
    2019-09-09
  • ionic3 懶加載

    ionic3 懶加載

    這篇文章主要介紹了ionic3 懶加載的相關(guān)資料,需要的朋友可以參考下
    2017-08-08
  • javascript設(shè)計(jì)模式 – 模板方法模式原理與用法實(shí)例分析

    javascript設(shè)計(jì)模式 – 模板方法模式原理與用法實(shí)例分析

    這篇文章主要介紹了javascript設(shè)計(jì)模式 – 模板方法模式原理,結(jié)合實(shí)例形式分析了javascript模板方法模式相關(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04
  • 微信小程序?qū)崿F(xiàn)紅包功能(后端PHP實(shí)現(xiàn)邏輯)

    微信小程序?qū)崿F(xiàn)紅包功能(后端PHP實(shí)現(xiàn)邏輯)

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)紅包功能,以及后端PHP實(shí)現(xiàn)邏輯,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 詳解在Javascript中進(jìn)行面向切面編程

    詳解在Javascript中進(jìn)行面向切面編程

    這篇文章主要介紹了Javascript面向切面編程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • js滾動(dòng)條回到頂部的代碼

    js滾動(dòng)條回到頂部的代碼

    js滾動(dòng)條回到頂部的代碼,里面的js代碼比較簡(jiǎn)單,很適合學(xué)習(xí)。
    2011-12-12
  • JavaScript編碼風(fēng)格指南(中文版)

    JavaScript編碼風(fēng)格指南(中文版)

    寫(xiě)作本文旨在加深自己印象,也為了更多人的了解到JS編碼風(fēng)格,提高自己的編碼質(zhì)量。想了解更多的內(nèi)容請(qǐng)閱讀《編寫(xiě)可維護(hù)的JavaScript》
    2016-08-08
  • js控制頁(yè)面的全屏展示和退出全屏顯示的方法

    js控制頁(yè)面的全屏展示和退出全屏顯示的方法

    這篇文章主要介紹了js控制頁(yè)面的全屏展示和退出全屏顯示的方法,實(shí)例分析了javascript控制頁(yè)面全屏效果的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • js變量聲明var使用與不使用的區(qū)別詳解

    js變量聲明var使用與不使用的區(qū)別詳解

    今天小編就為大家分享一篇關(guān)于js變量聲明var使用與不使用的區(qū)別詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • 利用JS將圖標(biāo)字體渲染為圖片的方法詳解

    利用JS將圖標(biāo)字體渲染為圖片的方法詳解

    在軟件開(kāi)發(fā)中肯定要用到圖標(biāo),比如下圖的?Groove?音樂(lè)中就用到了許多圖標(biāo)。一種獲取這些圖標(biāo)的方法是把?Groove?音樂(lè)截個(gè)圖,然后熟練地開(kāi)啟?Photoshop,開(kāi)始摳圖。這種方式很遜,效率也很低。本文將利用JS將圖標(biāo)字體渲染為圖片,需要的可以參考一下
    2022-05-05

最新評(píng)論