四天學會JS高階(學好vue的關鍵)——作用域解構箭頭函數(理論+實戰)(第一天)

一、作用域

提到作用域(作用域又分為局部作用域和全局作用域),就要想到變量。因為作用域規定了變量能夠被訪問的范圍(也就是作用域是為變量而服務的),為了避免全局變量污染這一情況,所以需要使用閉包函數創建隔離作用域。
這就是接下來我們要將作用域、作用域鏈、閉包,與變量聯系起來的思路。

1.1 局部作用域

首先局部作用域分為函數作用域和塊作用域。

函數作用域

函數作用域:就是在函數內部聲明的變量在函數外部不能使用

  function fn (e) {const i = 3console.log(i)console.log(e)}fn(4)//在函數外部會報錯console.log(`這是${i}`)console.log(`這是${e}`)

塊作用域

{ } 大花括號中的就是塊作用域 比如if語句 for循環等
在塊作用域中,代碼塊內部聲明的變量外部將【有可能】無法被訪問==》為什么是有可能===》因為如果是var變量,它不講塊作用域,所以外部可以訪問====》但是如果是let或者const變量,外部就不可以被訪問

  for (var i = 1; i <= 3; i++) {console.log(i)}console.log(i)for (let j = 1; j <= 3; j++) {console.log(j)}console.log(j)
  1. let 聲明的變量會產生塊作用域,var 不會產生塊作用域
  2. const 聲明的常量也會產生塊作用域
  3. 不同代碼塊之間的變量無法互相訪問
  4. 推薦使用 let 或 const

1.2 全局作用域

顧名思義,就是script標簽和.js文件的最外層就是所謂的全局作用域,在這里定義的變量在函數內部可以被訪問,函數內部就上上文講的局部作用域。
盡量少使用,避免變量污染。所謂的變量污染,大家可以理解為例如有個變量,它正在配合一個任務按部就班地進行著(也就是下面的例子,調用一次函數,count++一次),忽然有一天,因為它是全局變量,別人給他更改了一個很大值,這時候原先的任務還在執行,調用結果就是在別人給他更改的值的基礎上的++,這也就說明不能正常配合任務執行了,======》輕易地導致了全局變量的污染!

 //  count是全局變量 很容易被修改let count = 1function fn2 () {count++console.log(`函數被調用了${count}`)}fn2()

1.3 作用域鏈

本質上是底層的變量查找機制
也就是函數被執行時,優先從當前函數作用域中查找變量;如果當前作用域查找不到會一次逐級查找父級作用域知道全局作用域。
總結來說就是嵌套關系的作用域串聯起來形成了作用域,相同作用域鏈中按著從小到大的規則查找變量;子作用域能夠訪問父作用域,父作用域無法訪問子作用域(中的變量)。
在這里插入圖片描述

1.4 垃圾回收機制 (這部分待完善)

JS中內存的分配和回收都是自動完成的,內存在不使用的時候會被垃圾回收器自動回收。
正因為垃圾回收器的存在,所以大家在寫JS不太注意內存管理的問題
但如果不了解JS的內存管理機制,我們同樣非常容易成內存泄漏(內存無法被回收)的情況,所謂的內存泄漏就是:
不再用到的內存,沒有及時釋放

JS環境中分配的內存, 一般有如下生命周期:

  1. 內存分配:當我們聲明變量、函數、對象的時候,系統會自動為他們分配內存
  2. 內存使用:即讀寫內存,也就是使用變量、函數等
  3. 內存回收:使用完畢,由垃圾回收自動回收不再使用的內存
  4. 說明:
    全局變量一般不會回收(關閉頁面回收);
    一般情況下局部變量的值, 不用了, 會被自動回收掉

1.5 閉包

閉包 = 內層函數 + 外層函數的變量

兩種表達方式:

 function outer () {// 閉包 = 內層函數 + 外層函數的變量let a = 10表達方式一:// function fn () {/ /   console.log(a)/ /}// return一個函數 就可以使用閉包了//return fn表達方式二:因為fn===function fn()  也就是return直接指向了function函數return function fn () {console.log(a)}return }// outer()===fn===function fn()const fun = outer()fun()

利用閉包思想,來避免全部變量受污染的情況 最好的方法就是不使用全局變量

 <script>//  count是全局變量 很容易被修改// let count = 1// function fn2 () {//     count++//     console.log(`函數被調用了${count}次`)// }// fn2()// 閉包應用:內部聲明變量,實現數據的私有function fn () {let count = 1function fun () {count++console.log(`函數被調用${count}`)}return fun}const result = fn()result()</script>

二、預解析(了解)

2.1 變量提升 var

 <script>// var的變量提升// 所謂的變量提升就是當前變量在下面,上面使用的時候,就把所有var聲明的變量提升到當前作用域的最前面// 只提升聲明  不提升賦值// undefined 表示聲明變量未給值// console.log(num + '件')// var num = 10// console.log(num + '件');function fn () {console.log(num)var num = 10// 相當于 var num// console.log(num)// num=10}fn()</script>

2.2 函數提升

建議:使用let或者const,遵循先聲明后使用

  <script>// 1.會把所有函數聲明提升到當前作用域的前面// 2.提升函數聲明 不提升函數調用fn()function fn () {console.log('函數提升')}// 函數表達式 必須先聲明和賦值 后調用 否則報錯fun()var fun = function () {console.log('函數表達式')}// 因為上面這句話是使用var定義的,根據var的變量提升,所以會有// var fun// fun()// function() {//     console.log('函數表達式')// } 不可能實現聲明里面沒賦值就可以調用</script>

二、箭頭函數

2.1 動態參數

  1. arguments 是一個偽數組(具有length和索引號,但是它不具有數組的push(), pop(), forEach(), map(), filter() 等方法。),只存在于函數中
  2. arguments 的作用是動態獲取函數的實參
  3. 因為具有length和索引號,所以可以通過for循環依次得到傳遞過來的實參
  4. arguments的好處就是當我們傳入的實參數量不固定時,也就是一會求兩個數的和,一會求三個、四個…此時形參就是不固定的 此時使用arguments就非常好用 如下案例:
    <script>// 每一個函數里面默認都有一個動態參數arguments作為形參,所以不用特別將arguments寫進形參中// function getSum () {//     console.log(arguments)// }// getSum(2, 5, 56)function getSum () {let sum = 0// arguments動態參數 只存在于函數里面for (let i = 0; i < arguments.length; i++) {sum += arguments[i]}console.log(sum)}getSum(2, 34, 5, 67, 3)</script>

2.2 this問題

查找this的方法:從當前作用域查找,如果查找不到 就按照作用域鏈來查找

案例一:最簡單的函數調用中,this的指向問題
在這里有一個誤區,因為是fn調用的,所以this指向fn 注意:fn()是函數的定義,不是調用者。fn()在調用時,全寫為 window.fn(),所以調用者是window

function fn () {console.log(this)}fn() 

案例二:不要看到{},就認為是作用域
不要看到{},就認為是作用域,這樣會誤認為obj是函數的調用者,作用域是由函數和塊級語句創建的。我們判定作用域就是如果不是函數也不是塊級語句,+含有{},就不是作用域。
案例:指向的是函數的調用者=>對象

  const obj = {name: 'andy',sayHi: function () {console.log(this)//指向的是函數的調用者=>對象}}obj.sayHi()

案例三:全局作用域 指向window

// 全局作用域 指向windowconst obj1 = {uname: 'Pink老師',sayHi: () => {console.log(this)}}obj1.sayHi()

案例四:函數里面套箭頭函數,指向obj2
因為箭頭函數中沒有this 所以往上一層找 通過上一層的函數指向了函數的調用者obj2

// 指向objconst obj2 = {uname: 'pink老師',sayHi: function () {let i = 10const count = () => {console.log(this)}count()}}obj2.sayHi()

剩余與展開

剩余參數的定義是 . . .數組名 是一個真數組 與arguments異曲同工

 function getSum (...arr) {// console.log(arr)let sum = 0for (let i = 0; i < arr.length; i++) {sum += arr[i]}console.log(sum)}getSum(1, 2, 3)

但是,因為arguments需要在函數里面,這就帶來一些不方便,所以…arr,它可以實現求最值,合并數組等功能。

 <script>// const arr = [1, 2, 3]// console.log(...arr);// console.log(Math.max(...arr))  //里面放的只能是字符 不能是數字// 合并數組const arr1 = [1, 2, 3]const arr2 = [3, 4, 5]const arr3 = [...arr1, ...arr2]console.log(arr3);</script>

剩余參數的另一種應用

從前到后,形參和實參一一對應,但是如果實參過于多,后面的統一由剩余參數接收

 <script>function getSum (a, b, ...arr) {console.log(arr)  // 使用的時候不需要寫 ...}getSum(2, 3)getSum(1, 2, 3, 4, 5)</script>

2.3 箭頭函數

基本語法

 <script>// const fn = function () {//     console.log(123)// }// fn()// 1.箭頭函數基本語法// const fn = () => {//     console.log(123)// }// fn()// const fn = (x) => {//     console.log(x)// }// fn(1)// 2.只有一個形參的時候 可以省略小括號// const fn = x => {//     console.log(x)// }// fn(1)// 3.只有一行代碼的時候 可以省略大括號// const fn = x => console.log(x)// fn(1)// 4.只有一行代碼的時候 可以直接省略return// const fn = x => x + x// console.log(fn(1))// 5.箭頭函數可以直接返回個對象  將大括號轉化為小括號const fn = uname => ({ uname: uname })console.log(fn('劉德華'));</script>

使用箭頭函數求和

 <script>//箭頭函數中沒有arguments參數, 并且實參中傳入的是字符,可以通過...轉化為數組 很方便地實現數組中國數據的迭代const getSum = (...arr) => {let sum = 0for (let i = 0; i < arr.length; i++) {sum += arr[i]}return sum}const result = getSum(2, 3, 4)console.log(result);</script>
  <script>// 以前this的指向 誰調用的這個函數 this就指向誰// console.log(this)// function fn () {//     console.log(this)// }// window.fn()const obj = {name: 'anfy',sayHi: function () {console.log(this)  //指向的是對象}}obj.sayHi()const obj1 = {uname: 'pink老師',sayHi: () => {console.log(this)// this指向window  因為箭頭函數中沒有this  所以要去window中找}}obj1.sayHi()// 當前區域沒有this  按照作用域鏈往上一層找  函數里面有thisconst obj2 = {uname: 'pink老師',sayHi: function () {let i = 10const count = () => {console.log(this)}count()}}obj2.sayHi()btn.addEventListener('click', () => {console.log(this)})</script>

這里我有一個困擾 不知道大家有沒有 就是我在糾結 btn.addEventListener(‘click’, () => {
console.log(this)

    })  我想的是箭頭函數沒有this  它可以跑到外層  外層就是add  不就可以指向函數的調用者了嗎addEventListener 本身并不是一個作用域(scope),而是一個方法(method)。作用域是 JavaScript 中變量和函數可訪問性的區域。主要由函數和代碼塊(如 { ... })創建。既然箭頭函數中沒有this  往外走到父級作用域  所以也就來到了全局作用域  全局作用域指向windowaddEventListener 的回調中,外層上下文并不是 addEventListener 函數本身,而是定義箭頭函數的那個作用域。 箭頭函數被定義在一個全局作用域或模塊作用域中
 <script>// 1.以前this的指向 誰調用的這個函數 this就指向誰// console.log(this)// function fn () {//     console.log(this)// }// window.fn()   //===fn()const obj = {name: 'anfy',sayHi: function () {console.log(this)  //指向的是函數的調用者,也就是對象}}obj.sayHi()const obj1 = {uname: 'pink老師',sayHi: () => {console.log(this)// this指向window  因為箭頭函數中沒有this  所以要去window中找}}obj1.sayHi()// 當前區域沒有this  按照作用域鏈往上一層找  函數里面有thisconst obj2 = {uname: 'pink老師',sayHi: function () {let i = 10const count = () => {console.log(this)}count()}}obj2.sayHi()btn.addEventListener('click', () => {console.log(this)})</script>

三、 解構賦值

解構賦值是一種快速為變量賦值的簡潔語法,本質上仍然是為變量賦值
分為:數組解構
對象解構

3.1 數組解構

數組解構是將數組的單元值快速批量賦值給一系列變量的簡潔語法.
基本語法:
1.左側的[ ]用于聲明變量因為是多個,所以是批量聲明變量,右側數組的單元值將被賦值給左側的變量中。
2.變量的順序對應數組單元值的位置依次進行賦值操作。

 // 數組解構 賦值const arr = [100, 60, 80]// const [max, min, avg] = arrconst [max, min, avg] = [100, 60, 80]console.log(max)console.log(min)console.log(avg)// 交換兩個變量的值let a = 1let b = 2;[b, a] = [a, b]console.log(a, b);

必須加分號的兩種情況:

  // 1.立即執行函數要加分號(function () { })();(function () { })()// 2.使用數組的時候const arr = [1, 2, 3]const str = 'pink'// 真正數組前面要加上分號;[1, 2, 3].map(function (item) {console.log(item)})// 數組名不用加上分號// arr.map(function (item) {//     console.log(item)// })

數組解構的一些細節:

// 1.變量多 單元值少  undefined// const [a, b, c, d] = [1, 2, 3]// console.log(a)// console.log(b)// console.log(c)// console.log(d)// 2.變量少 單元值多const [e, f] = [1, 2, 3]console.log(e)console.log(f)// 3.剩余參數 變量少 單元制多const [g, h, ...i] = [1, 2, 3, 4]console.log(g)console.log(h)console.log(i)// 4.防止有undefined傳單元值  設置默認值// const [a = 0, b = 0] = []// console.log(a)// console.log(b)// const [c = '手機', d = '華為'] = ['小米']// console.log(c)// console.log(d)// 5.按需導入  忽略返回值  以逗號隔開// const [a, b, , d] = [1, 2, 3, 4]// console.log(a)// console.log(b)// console.log(d)// 6.支持多維數組結構// 一般的多維數組// const arr = [1, 2, [3, 4]]  //二維// console.log(arr[0])// console.log(arr[1])// console.log(arr[2][0]);// 數組解構const [a, b, [c, d]] = [1, 2, [3, 4]]  //二維console.log(a)console.log(b)console.log(c)console.log(d);

3.2 對象解構

對象解構是將對象屬性和方法快速批量賦值給一系列變量的簡潔語法

對象解構的幾種情況:

 <script>// 1.對象解構// const obj = {//     // 對象里面為屬性  對象外面的為變量//     uname: 'pink老師',//     age: 18// }// 2.解構的語法  變量名字 屬性名字相同  // const { uname, age } = {//     // 對象里面為屬性//     uname: 'pink老師',//     age: 18// }// console.log(uname)// console.log(age)// 3.對象解構的變量名 可以重新改名  舊變量名:新變量名// const { uname: username, age } = { uname: 'pink老師', age: 18 }// console.log(username)// console.log(age);// 4.數組對象解構const pig = [{uname: '佩奇',age: 18}]const [{ uname, age }] = pigconsole.log(uname);</script>

多級對象解構

 // 多級對象解構 也就是對象里面套對象const pig = {name: '佩奇',family: {mother: '豬媽媽',father: '豬爸爸',sister: '喬治'},age: 7}const { name, family: { mother, father, sister } } = pigconsole.log(name)console.log(mother)console.log(father)console.log(sister);

對象解構綜合案例

  <script>// 1. 這是后臺傳遞過來的數據const msg = {"code": 200,"msg": "獲取新聞列表成功","data": [{"id": 1,"title": "5G商用自己,三大運用商收入下降","count": 58},{"id": 2,"title": "國際媒體頭條速覽","count": 56},{"id": 3,"title": "烏克蘭和俄羅斯持續沖突","count": 1669},]}// 需求一,將以上msg對象 采用對象解構的方式 只選出data數據使用來作為渲染頁面的數據// const { data } = msg// console.log(data)// 需求2: 上面msg是后臺傳遞過來的數據,我們需要把data選出當做參數傳遞給 函數// msg雖然很多屬性 但是我們利用解構只要data值// const { data } = msg// 所以這個{}相當于在說要對那個對象進行對象解構function render ({ data }) {// const { data } = arrconsole.log(data)}render(msg)// 需求3, 為了防止msg里面的data名字混淆,要求渲染函數里面的數據名改為 myDatafunction render ({ data: myData }) {console.log(myData)}render(msg)</script>

forEach方法

<script>const arr = ['red', 'green', 'pink']// item是必須要寫的 // foreach就是純遍歷  加強版的for循環  適合于遍歷數組對象const result = arr.forEach(function (item, index) {console.log(item)//每個數組元素console.log(index)//索引號})console.log(result)//不返回值</script>

綜合案例

綜合案例一:

小熱身,先講一個結合forEach方法小案例:


首先這個案例其實就是頁面已經設計好了,只要我們拿到數據,渲染到頁面就行了,下面的item就是需要填寫的數據,這些數據如果沒有js,我們填入的都是死的數據,現在有了js,數據就變成活得了,將獲得的數據填寫在item中,然后將item追加到list大頁面中。又下面的item都是字符串,所以我們采用字符串拼接,最后追加到list中。
![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/8aad29cd731a4d18903cda7d7f5609d0.png)
***完整代碼 我貼在最后了***
```javascript//1.聲明一個字符串變量let str = ''// 2.遍歷數據,遍歷8次goodsList.forEach(item => {// console.log(item)const { id } = item// 對象解構const { name, price, picture } = item//字符串str += `<div class="item"><img src=${picture} alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})//最后追加document.querySelector('.list').innerHTML = str

filter 篩選數組 返回的是真數組

<script>const arr = [10, 20, 30]// const newArr = arr.filter(function (item, index) {//     // 也有用item和index//     // console.log(item)//     // console.log(index)//     return item >= 20// })// console.log(newArr);// 寫成箭頭函數const newArr = arr.filter(item => item >= 20)console.log(newArr);</script>

綜合案例二、渲染函數——篩選(filter)

完整代碼見 ## 完整代碼2

  // 1.渲染函數 封裝function render (arr) {//聲明空字符串let str = ''//遍歷數組arr.forEach(item => {// 解構const { name, picture, price } = itemstr += `<div class="item"><img src=${picture} alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})//追加給listdocument.querySelector('.list').innerHTML = str}render(goodsList)//頁面一打開就需要渲染// 2.過濾篩選document.querySelector('.filter').addEventListener('click', e => {const { tagName, dataset } = e.target//判斷if (tagName === 'A') {let arr = goodsListif (dataset.index === '1') {arr = goodsList.filter(item => item.price > 0 && item.price <= 100)} else if (dataset.index === '2') {arr = goodsList.filter(item => item.price >= 100 && item.price <= 300)} else if (dataset.index === '3') {arr = goodsList.filter(item => item.price >= 300)}//渲染函數render(arr)}})

完整代碼1

<!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>商品渲染</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.list {width: 990px;margin: 0 auto;display: flex;flex-wrap: wrap;padding-top: 100px;}.item {width: 240px;margin-left: 10px;padding: 20px 30px;transition: all .5s;margin-bottom: 20px;}.item:nth-child(4n) {margin-left: 0;}.item:hover {box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);transform: translate3d(0, -4px, 0);cursor: pointer;}.item img {width: 100%;}.item .name {font-size: 18px;margin-bottom: 10px;color: #666;}.item .price {font-size: 22px;color: firebrick;}.item .price::before {content: "¥";font-size: 14px;}</style>
</head><body><div class="list"><!-- <div class="item"><img src="" alt=""><p class="name"></p><p class="price"></p></div> --></div><script>const goodsList = [{id: '4001172',name: '稱心如意手搖咖啡磨豆機咖啡豆研磨機',price: '289.00',picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',},{id: '4001594',name: '日式黑陶功夫茶組雙側把茶具禮盒裝',price: '288.00',picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',},{id: '4001009',name: '竹制干泡茶盤正方形瀝水茶臺品茶盤',price: '109.00',picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',},{id: '4001874',name: '古法溫酒汝瓷酒具套裝白酒杯蓮花溫酒器',price: '488.00',picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',},{id: '4001649',name: '大師監制龍泉青瓷茶葉罐',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',},{id: '3997185',name: '與眾不同的口感汝瓷白酒杯套組1壺4杯',price: '108.00',picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',},{id: '3997403',name: '手工吹制更厚實白酒杯壺套裝6壺6杯',price: '99.00',picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',},{id: '3998274',name: '德國百年工藝高端水晶玻璃紅酒杯2支裝',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',},]//1.聲明一個字符串變量let str = ''// 2.遍歷數據,遍歷8次goodsList.forEach(item => {// console.log(item)const { id } = item// 對象解構const { name, price, picture } = item//字符串str += `<div class="item"><img src=${picture} alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})//最后追加document.querySelector('.list').innerHTML = str</script>
</body></html>

完整代碼2

<!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>商品渲染</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.list {width: 990px;margin: 0 auto;display: flex;flex-wrap: wrap;}.item {width: 240px;margin-left: 10px;padding: 20px 30px;transition: all .5s;margin-bottom: 20px;}.item:nth-child(4n) {margin-left: 0;}.item:hover {box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);transform: translate3d(0, -4px, 0);cursor: pointer;}.item img {width: 100%;}.item .name {font-size: 18px;margin-bottom: 10px;color: #666;}.item .price {font-size: 22px;color: firebrick;}.item .price::before {content: "¥";font-size: 14px;}.filter {display: flex;width: 990px;margin: 0 auto;padding: 50px 30px;}.filter a {padding: 10px 20px;background: #f5f5f5;color: #666;text-decoration: none;margin-right: 20px;}.filter a:active,.filter a:focus {background: #05943c;color: #fff;}</style>
</head><body><div class="filter"><a data-index="1" href="javascript:;">0-100</a><a data-index="2" href="javascript:;">100-300</a><a data-index="3" href="javascript:;">300元以上</a><a href="javascript:;">全部區間</a></div><div class="list"><!-- <div class="item"><img src="" alt=""><p class="name"></p><p class="price"></p></div> --></div><script>const goodsList = [{id: '4001172',name: '稱心如意手搖咖啡磨豆機咖啡豆研磨機',price: '289.00',picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',},{id: '4001594',name: '日式黑陶功夫茶組雙側把茶具禮盒裝',price: '288.00',picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',},{id: '4001009',name: '竹制干泡茶盤正方形瀝水茶臺品茶盤',price: '109.00',picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',},{id: '4001874',name: '古法溫酒汝瓷酒具套裝白酒杯蓮花溫酒器',price: '488.00',picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',},{id: '4001649',name: '大師監制龍泉青瓷茶葉罐',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',},{id: '3997185',name: '與眾不同的口感汝瓷白酒杯套組1壺4杯',price: '108.00',picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',},{id: '3997403',name: '手工吹制更厚實白酒杯壺套裝6壺6杯',price: '99.00',picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',},{id: '3998274',name: '德國百年工藝高端水晶玻璃紅酒杯2支裝',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',},]// 1.渲染函數 封裝function render (arr) {//聲明空字符串let str = ''//遍歷數組arr.forEach(item => {// 解構const { name, picture, price } = itemstr += `<div class="item"><img src=${picture} alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`})//追加給listdocument.querySelector('.list').innerHTML = str}render(goodsList)//頁面一打開就需要渲染// 2.過濾篩選document.querySelector('.filter').addEventListener('click', e => {const { tagName, dataset } = e.target//判斷if (tagName === 'A') {let arr = goodsListif (dataset.index === '1') {arr = goodsList.filter(item => item.price > 0 && item.price <= 100)} else if (dataset.index === '2') {arr = goodsList.filter(item => item.price >= 100 && item.price <= 300)} else if (dataset.index === '3') {arr = goodsList.filter(item => item.price >= 300)}//渲染函數render(arr)}})</script>
</body></html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12315.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12315.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12315.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何排查域名網站無法訪問了頁面報500錯誤

本周有一個客戶&#xff0c;購買Hostease的虛擬主機&#xff0c;詢問我們的在線客服&#xff0c;域名網站無法訪問了報500錯誤頁面&#xff0c;怎么辦&#xff1f;我們為用戶提供相關教程&#xff0c;用戶很快解決了遇到的問題。在此&#xff0c;我們分享這個操作教程&#xff…

bugfix:遇見“隱形字符”:ⅰ與i的編碼迷局

前言 在軟件開發的世界里&#xff0c;遇到各種奇奇怪怪的bug是在所難免的。今天&#xff0c;我就遭遇了一個看似簡單實則棘手的問題——用戶反饋賬號無法登錄&#xff0c;系統一直提示“賬號不存在”。一番抽絲剝繭后&#xff0c;我發現問題竟然出在一個不起眼的字符上&#x…

Go微服務: Gin框架搭建網關, 接入熔斷器,鏈路追蹤以及服務端接入限流和鏈路追蹤

概述 本文使用最簡單和快速的方式基于Gin框架搭建一個微服務的網關調用微服務的場景網關作為客戶端基于RPC調用某一服務端的服務并接入熔斷和限流以及鏈路追蹤具體場景&#xff1a;通過網關API查詢購物車里的數據在最后&#xff0c;會貼上網關和購物車服務的代碼倉庫 服務端搭…

避雷:搭建AI知識庫注意事項

AI知識庫作為信息存儲和進行智能處理的核心部分&#xff0c;受到越來越多企業的重視。為了更好地發展&#xff0c;企業也紛紛開始搭建AI知識庫。然而&#xff0c;在搭建AI知識庫的過程中&#xff0c;也有很多雷區容易踩到&#xff0c;導致項目延遲、效果不佳甚至失敗。所以&…

《控制系統實驗與綜合設計》計控第三次(含程序和題目)

實驗七 采樣控制系統的分析 一、實驗完成任務 1、熟悉用 LF398 組成的采樣控制系統&#xff1b; 2、通過本實驗理解采樣定理和零階保持器的原理及其實現方法&#xff1b; 3、觀察系統在階躍作用下的穩態誤差。 4.、研究開環增益 K 和采樣周期 T 的變化對系統動態性能的影響…

Linux基礎之進程-進程狀態

目錄 一、進程狀態 1.1 什么是進程狀態 1.2 運行狀態 1.2 阻塞狀態 1.3 掛起狀態 二、Linux操作系統上具體的進程狀態 2.1 狀態 2.2 R 和 S 狀態的查看 2.3 后臺進程和前臺進程 2.4 休眠狀態和深度休眠狀態 一、進程狀態 1.1 什么是進程狀態 首先我們知道我們的操作系…

分布式光伏監控系統功能模塊詳解

目前&#xff0c;分布式光伏發電系統的總容量比較小&#xff0c;并且光伏電站的功率受外界環境影響容易出現大起大落的現象。這使電壓調整變得很困難。光伏電站運行維護人員不足&#xff0c;長時間不保養維護會影響光伏電站的發電效率。針對上述問題&#xff0c;鷓鴣云基于無線…

天銳綠盾|設計院圖紙透明加密軟件、制造業文件資料防止外泄

#圖紙加密軟件# 天銳綠盾是一家專注于數據安全解決方案的提供商&#xff0c;其產品主要為企業級用戶設計&#xff0c;旨在保護敏感信息和知識產權免遭未經授權的訪問或泄露。"天銳綠盾"的圖紙透明加密軟件和機械制造業文件資料防止外泄系統&#xff0c;是專為設計院…

JS中的宏任務和微任務

JavaScript 引擎是建立在一個事件循環系統之上的&#xff0c;它實時監控事件隊列&#xff0c;如果有事件就執行&#xff0c;如果沒有事件就等待。事件系統是一個典型的生產消費模式&#xff0c;生產者發出事件&#xff0c;接收者監聽事件&#xff0c;在UI 開發中是常見的一個設…

Modbus TCP轉CAN網關在不同行業中的應用以及其使用上的優勢

倍訊科技Modbus TCP轉CAN網關通常被用于工業自動化領域&#xff0c;特別是在需要連接現有Modbus TCP網絡和CAN總線設備的場景中。以下是該網關在不同行業中的應用以及其使用上的優勢&#xff1a; 1. 制造業&#xff1a; - 在制造業中&#xff0c;各種類型的設備和機器通常使用不…

Java項目實現報文數據校驗注解方式(必輸項、值大小)

普通項目 導入校驗依賴 <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>4.1.0.Final</version></dependency><dependency><groupId>javax.validation</…

Docker安裝Redis,并在 Visual Studio Code 中使用它

Docker安裝Redis 查找Redis docker search Redis完整結果 PS C:\Users\cheng> docker search Redis NAME DESCRIPTION STARS OFFICIAL redis Redis is an open …

System V IPC(進程間通信)機制詳解

文章目錄 一、引言二、System V IPC的基本概念1、IPC結構的引入2、IPC標識符&#xff08;IPC ID&#xff09;3、S ystem V的優缺點 三、共享內存&#xff08;Shared Memory&#xff09;1、共享內存的基本概念2、共享內存的創建&#xff08;shmget&#xff09;3、共享內存的附加…

C++:并發保護

一、前言 本文將會通過保護一個數據討論&#xff1a;互斥鎖、雙重檢查鎖、 std::once_flag 類、 std::call_once() 函數、單例模式、使用局部靜態變量實現單例模式等。 二、保護共享數據 假設我們需要某個共享數據&#xff0c;而它創建起來開銷不菲。因為創建它可能需要建立…

vim中的替換

:[range]s/pattern/replacement/flags 這里各部分的含義是&#xff1a; :[range]&#xff1a;可選的行范圍&#xff0c;用于指定在哪些行之間進行替換。如果省略&#xff0c;則默認為當前行。例如&#xff0c;1,10 表示在第1行到第10行之間替換&#xff0c;% 表示在整個文件中…

python的文件操作及函數式編程介紹

五、文件操作 1、讀取鍵盤輸入 input 獲取標準輸入&#xff0c;數據類型統一為字符串 #!/usr/bin/python # -*- coding: UTF-8 -*- str input("請輸入&#xff1a;") print&#xff08;"你輸入的內容是: ", str&#xff09; 這會產生如下的對應著輸入的…

KeyShot 2023.3 Pro for mac/win:完美融合3D渲染與動畫制作

在當今數字化時代&#xff0c;視覺內容的創作和表現越來越受到重視。無論是產品設計、建筑規劃&#xff0c;還是影視特效&#xff0c;都需要具備出色的3D渲染和動畫制作工具來展現創意和想法。而作為業內領先的3D渲染和動畫制作軟件之一&#xff0c;KeyShot 2023.3 Pro在這個領…

電腦剛開機的時候不卡,用一會就變卡頓了…怎么回事?

前言 昨天咱們聊到舊電腦更換了固態硬盤之后&#xff0c;開機就會變快的事情&#xff0c;這個確實是可行且有效的升級電腦辦法之一。 看完這篇之后&#xff0c;切莫著急升級電腦硬件配置&#xff0c;因為這里的坑比你想象的還要多。 從機械硬盤測試的數據和固態硬盤的測試數…

類與面向對象編程(Object-Oriented Programming, OOP)

類與面向對象編程&#xff08;Object-Oriented Programming, OOP&#xff09;&#xff08;一&#xff09; 對象比較&#xff1a;‘is’ 對比 ‘’ 當我還是個孩子的時候&#xff0c;我們的鄰居擁有一對雙胞胎貓咪。它們看起來幾乎一模一樣—同樣的炭黑色毛發和同樣銳利的綠色…

2024年港口危貨安全管理證報名條件

危化品安全員證報考條件 1、職業道德良好&#xff0c;身體健康&#xff0c;年齡不超過60周歲(法定代表人除外). 2、建筑施工企業的在職人員。 3、學歷及要求: (1)建筑施工企業主要負責人應為大專以上學歷&#xff0c;需大專以上學歷&#xff0c;除企業法人外&#xff0c;其他…