javascript<——>進階

一、作用域:變量可以被訪問的范圍

1.局部作用域

1.1函數作用域

在函數內部聲明的變量,在函數內部被訪問的,外部無法直接訪問。

總結:1、函數內部聲明的變量,在函數外部無法直接訪問

2、函數的參數也是函數內部的局部變量

3、不同函數內部聲明的變量無法互相訪問

4、函數執行完畢后,函數內部的變量事件被清空

1.2塊作用域

有“{}”的包裹的代碼稱為代碼塊,內部聲明的變量外部將【有可能】無法被訪問

###let /const聲明的變量產生塊作用域,var聲明的不會產生塊級作用域

2.全局作用域

寫在<script>標簽的或者寫在js文件的,盡可能少聲明全局作用域,防止全局變量被污染

3.作用域鏈

本質是底層的變量查找機制:(1)函數執行時,優先查找當前函數作用域中查找

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(2)查不到則依次逐級查找父級作用域直到全局作用域

###子作用域可以訪問父作用域,但是父作用域無法訪問子作用域

###相同作用域鏈按從小到大規則查找變量

4.js垃圾回收機制(GC)

4.1內存生命周期

(1)分配內存:聲明變量、函數、對象時,系統自動分配內存

(2)內存使用:讀寫內存,使用函數,變量

(3)內存回收:使用完畢,垃圾回收機制自動回收不在使用的內存

###全局變量一般不會回收(關閉頁面回收),

(4)內存泄漏:程序中分配的內存由于某種原因,程序無法釋放或者未釋放。

??算法說明:

1.棧(操作系統):由操作系統自動分配釋放函數的參數值,局部變量等,基本數據類型放到棧里面

2.堆(操作系統):一般由程序員分配釋放,不釋放,則垃圾回收機制回收。復雜數據類型放到堆里面

4.2垃圾回收算法

(1)引用計數法

跟蹤記錄被引用的次數,引用一次則記錄一次,多次引用會累加++,減少一次引用就--

次數為0,回收

缺點:嵌套使用。兩個對象相互引用,盡管它們不再使用,GC不會進行回收,內存泄漏

(2)標記清除法

核心:1.將“不再使用的對象”定義為“無法達到的對象”。

? ? ? ? ? ?2.從根部出發定時掃描內存中的對象。凡是從根部到達的對象,都是還需要使用的。

? ? ? ? ? ?3.無法觸及的對象被標記為不再使用,稍后進行回收。

5.閉包

一個函數對周圍狀態的引用捆綁在一起,內層函數中訪問到其外層函數作用域,會產生內存泄漏

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

<script>
function outer(){let a = 1function fn(){console.log(a)}return fn
}
const fun = outer()
fun()
</script>
//外層函數可以訪問內層函數的變量
//const fun = outer() = fn = function fn(){}
//調用fun()

作用:閉包的應用:實現數據的私有,封閉數據。做個統計函數調用次數,調用一次就++

外部可以訪問函數內部的變量

問題:內存泄漏

<script>function count(){let i = 0function fn(){i++console.log(`函數被調用了${i}次`)  }return fn
}
const fun = count()</script>

6.變量提升

把var聲明的變量提升到 當前作用域的最前面。

只提升聲明,不提升賦值

總結:

  1. 變量在未聲明即被訪問時會報語法錯誤

  2. 變量在聲明之前即被訪問,變量的值為 undefined

  3. let 聲明的變量不存在變量提升,推薦使用 let

  4. 變量提升出現在相同作用域當中

  5. 實際開發中推薦先聲明再訪問變量

<script>
function(){console.log(num)var num = 10
}
fun()等價于
function(){var numconsole.log(num)num = 10
}
fun()
</script>

二、函數進階

1.函數提升(只提升聲明,不提升調用)

聲明之前調用

函數表達式 必須先聲明和賦值,后調用,否則報錯。

總結:1、函數提升能夠使函數的聲明調用更靈活

2、函數表達式不存在提升的現象

3、函數提升出現在相同作用域當中

2.函數參數

###默認值

總結:1、聲明函數時為形參賦值即為參數的默認值

2、如果參數未自定義默認值時,參數的默認值為undefined

3、調用函數時沒有差引入對應實參時,參數的默認值被當做實參傳入

2.1動態參數

arguments是一個偽數組?只存在于 函數里面

作用是動態的獲取函數的實參

可以通過for循環依次得到傳遞過來的參數

2.2剩余參數

(1)...是語法符號,置于最末函數形參之前,用于獲取多余的實參

(2)借助...獲取的剩余參數,是個真數組

  <script>function getSum(a,b,...arr){console.log(arr);}getSum(2,3,4,5,6,7)getSum(1,2,3,4,5,6,7,8,9)</script>

##使用場景:用于獲取多余的實參

##和動態參數的區別是什么?

? ? ? ? 動態參數是偽數組;

? ? ? ? 剩余參數是真數組

??展開運算符【數組中使用】:將數組的數字全展開

      const arr = [1,2,3,4,5]console.log(...arr)console.log(Math.max(...arr));//求最大值console.log(Math.min(...arr));//求最小值

合并數組:

      const arr1 = [1,2,3]const arr2 = [4,5,6]const arr3 = [...arr1,...arr2]console.log(arr3);// [1,2,3,4,5,6]

3.箭頭函數

(1)基本語法

const fn=()=>{

}

##只有一個形參時,可以省略小括號

const fn = x=>{


}

##只有一行代碼時,可以省略大括號和return

const fn = (x,y) =>x+y

console.log(fn(1,2))

##箭頭函數可以直接返回同一個對象

const fn1 = uname=>({uname:name})

console.log('劉德華')

總結:

1、箭頭函數屬于表達式函數,因此不存在函數提升

2、箭頭函數只有一個參數時可以省略圓括號()

3、箭頭函數函數體只有一行時代碼可以省略花括號{},并自動作為返回值被返回

(2)箭頭函數參數

只有剩余參數,沒有動態參數arguments

(3)箭頭函數this

箭頭函數不會創建自己的this,從自己的作用域鏈的上一層沿用this

三、解構賦值

1.數組解構 :

將數組的單元值快速批量賦值給一系列變量的簡介語法

<script>// 以下代碼是否會正常執行,如果不會,如何改正const [min, avg, max] = [100,200,300];//必須加分號(function() {console.log(min);})();</script>
<script>const arr = [60,100,80]const [max,min avg] = arr
//將按照順序賦值給變量console.log(max)
</script>

交換變量

<script>
let a = 1
let b = 2;
const [b,a]=[a,b]
console.log(a,b)
</script>
<script>1. 變量多, 單元值少 , undefinedconst [a, b, c, d] = [1, 2, 3]console.log(a) // 1console.log(b) // 2console.log(c) // 3console.log(d) // undefined2. 變量少, 單元值多const [a, b] = [1, 2, 3]console.log(a) // 1console.log(b) // 23.  剩余參數 變量少, 單元值多const [a, b, ...c] = [1, 2, 3, 4]console.log(a) // 1console.log(b) // 2console.log(c) // [3, 4]  真數組4.  防止 undefined 傳遞const [a = 0, b = 0] = [1, 2]const [a = 0, b = 0] = []console.log(a) // 1console.log(b) // 25.  按需導入賦值const [a, b, , d] = [1, 2, 3, 4]console.log(a) // 1console.log(b) // 2console.log(d) // 4const arr = [1, 2, [3, 4]]console.log(arr[0])  // 1console.log(arr[1])  // 2console.log(arr[2])  // [3,4]console.log(arr[2][0])  // 3// 多維數組解構const [a, b, [c, d]] = [1, 2, [3, 4]]console.log(a) // 1console.log(b) // 2console.log(c) // 3console.log(d) // 4</script>

2.對象解構

<script>// 對象解構const obj = {uname: 'pink老師',age: 18}obj.unameobj.age //const uname = 'red老師'解構的語法const { uname, age } = {age: 18, uname: 'pink老師' }// 等價于 const uname =  obj.uname//要求屬性名和變量名必須一致才可以
</script>

3.多級對象解構

<script>const pig = {name: '佩奇',family: {mother: '豬媽媽',father: '豬爸爸',sister: '喬治'},age: 6}// // 多級對象解構const { name, family: { mother, father, sister } } = pig
</script>

4.多級數組對象解構

 <script>//多級對象數組解構const person = [{name: '佩奇',family: {mother: '豬媽媽',father: '豬爸爸',sister: '喬治'},age: 6}]const [{ name, family: { mother, father, sister } }] = personconsole.log(name)console.log(mother)console.log(father)console.log(sister)</script>

5.多級對象解構案例

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

###forEach()方法

用于調用數組的每個元素,并將元素傳遞給回調函數

注意:

1、forEach主要是遍歷數組

2、參數當前數組元素使必須要寫的,索引號可選。

  <script>// forEach 就是遍歷  加強版的for循環  適合于遍歷數組對象const arr = ['red', 'green', 'pink']const result = arr.forEach(function (item, index) {console.log(item)  // 數組元素 red  green pinkconsole.log(index) // 索引號})// console.log(result)</script>

###篩選數組filter方法

filter()方法創建的一個新數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素

使用場景:篩選數組符合條件的元素,并返回篩選之后元素的新數組

語法:

  <script>const arr = [10, 20, 30]// const newArr = arr.filter(function (item, index) {//   // console.log(item)//   // console.log(index)//   return item >= 20// })// 返回的符合條件的新數組const newArr = arr.filter(item => item >= 20)console.log(newArr)</script>

###渲染商品案例

 <script>// 2. 初始化數據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',},]function render(arr) {let str = ''arr.forEach(item => {const { name, price, picture } = itemstr += `<div class="item"><img src="${picture}" alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`});document.querySelector('.list').innerHTML = str}render(goodsList)document.querySelector('.filter').addEventListener('click', e => {const { tagName, dataset } = e.targetif (tagName == 'A') {//console.log(11);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>

四、構造函數與數據常用函數

1.深入對象

1.1創建對象三種方式

(1)利用對象字面量創建對象

const 0 = {

? ? ? ? name :?'abc'

}

(2)利用new Object創建對象

const 0 = new Object({name:'abc'})

(3)利用構造函數創建對象

1.2構造函數

一種特殊的函數,主要用來初始化對象。

##使用new關鍵字的調用函數行為被稱為實例化

##實例化構造函數時沒有參數可以省略

##構造函數內部無需寫return,返回值即新創建的對象

##構造函數內部的return返回值無效,所以不要寫return

##new Object()new Date()也是實例化構造函數

兩個約定:

<1>命名大寫字母開頭

<2>它們只能由“new”操作符來執行

<script>function Pig(uname,age){this.uname = unamethis.age = age
}const p = new Pig('peiqi',6)const q = new Pig('qiaozhi',3)console.log(p,q)
</script>

??實例化執行過程

(1)創建新對象

(2)構造函數this指向新對象

(3)執行函數構造代碼,修改this,添加新屬性

(4)返回新的對象

1.3實例成員和靜態成員

1.3.1實例成員

通過構造函數創建的對象稱為實例對象,實例對象中的屬性和方法稱為實例成員(實例屬性和實例方法)

1.3.2靜態成員

構造函數的屬性和方法被稱為靜態成員

<script>function Pig(name){this.name = name
}
Pig.eyes = 2//靜態屬性
Pig.sayHi = function(){//靜態方法console.log(this)
}
Pig.sayHi()
console.log(Pig.eyes)//2
</script>

說明:

1.靜態成員只能構造函數來訪問

2.靜態方法中的this指向構造函數

2.內置構造函數

1.Object

.keys(obj):返回所有屬性名

.values(obj):獲得所有的屬性值【返回的是數組】

 const o = { uname: 'pink', age: 18 }// 1.獲得所有的屬性名console.log(Object.keys(o))  //返回數組['uname', 'age']// 2. 獲得所有的屬性值console.log(Object.values(o))  // ?['pink', 18]

.assign(new,old):對象拷貝

 // 3. 對象的拷貝const o = { uname: 'pink', age: 18 }// const oo = {}// Object.assign(oo, o)// console.log(oo)//對象中添加屬性Object.assign(o, { gender: '女' })console.log(o)

2.Array

方法作用說明
filter過濾數組返回新數組,返回的是篩選滿足條件的數組與數組元素
forEach遍歷數組不返回數組,經常用于查找遍歷數組元素
map迭代數組返回新數組,返回的是處理后的數組元素,想要使用返回的新數組
reduce累計器返回累計處理的結果,經常用于求和等

join

拼接數組元素拼接成字符串,返回字符串
find查找元素返回符合測試條件的第一個數組,如果沒有符合條件的則返回undefined
every檢測數組所有元素是否都符合指定條件如果都符合,返回true,否則返回false
sort排序對原數組單元值進行排序
from偽數組轉換為真數組返回真數組

<script>const arr =  [1,3,5,7,9]const result = arr.reduce((a,b)=>(a+b),10)console.log(result)//35
</script>

(1)reduce(function(prev,curret){return prev+curret},start)

prev:代表初始值

curret:代表累加的值

start:初始值具體數字

###

1.如果沒有初始值,則上一次的值以數組的第一個數組元素的值。

2.每一次循環,把返回值給作為 下一次循環的上一次值。

3.如果有初始值,則起始值作為上一次值。

  <script>const arr = [{name: '張三',salary: 10000}, {name: '李四',salary: 10000}, {name: '王五',salary: 20000},]const money = arr.reduce((prev, item) => prev + item.salary * 1.3, 0)console.log(money)</script>

包裝類型:

字符串、數值、布爾類型數據是js底層使用Object構造函數“包裝”來的,即為包裝類型

3.String

.split【‘分隔符’】:把字符串轉換成數組(和join相反)

.substring【第一個索引,最后一個索引】截取字符串

.startsWith(檢測字符串,【檢測位置的索引號】),檢測是否以某字符開頭

.includes(搜索的字符串,檢測的字符串位置索號),判斷一的字符串是否包含在另一個字符串中,根據情況返回true或false

.replace(代替字符串)

4.Number

.toFixed:設置保留小數位的長度,四舍五入。

3.綜合案例

五、深入面向對象

1.編程思想

(1)面向過程

分析解決問題的步驟,然后用函數一步一步地實現,使用的時候調用

優點:性能高

缺點:沒有面向易維護,復用,擴展

(2)面向對象(oop)

優點:易維護、復用、擴展,使系統更加易于維護,更加靈活

缺點:性能低

分解為一個個對象,然后對象之間分工和合作。

###特性:

【1】封裝性:封裝代碼,js面向對象可以通過構造函數實現的封裝,同時將變量和函數組合到一起并能通過this實現數據的共享,所不同的是借助構造函數創建出來的實例對象之間互相不影響。

總結:

1、構造函數體現了面向對象的封裝特性

2、構造函數實例創建的對象彼此獨立,互不影響。

【2】繼承性:繼承接口

【3】多態性

2.構造函數

存在浪費內存的問題

3.原型對象

構造函數通過原型分配的函數是所有對象所共享的

###js規定,每一個構造函數都有一個prototype屬性,指向另一個對象,所以我們也稱為原型對象

###這個對象可以掛載函數,對象實例化不會多次創建原型上函數,節約內存

###我們可以把那些不變的方法,直接定義為prototype對象上,這樣所有對象的實例就可以共享這些方法

###構造函數和原型對象中的this都指向實例化的對象

原型作用:
(1)共享方法

(2)可以把那些不變的方法,直接定義在prototype對象上

構造函數和原型里面的this指向誰?

指向實例化對象

constructor 屬性

在哪里? 每個原型對象里面都有個constructor 屬性(constructor 構造函數)

作用:該屬性指向該原型對象的構造函數, 簡單理解,就是指向我的爸爸,我是有爸爸的孩子

使用場景:

如果有多個對象的方法,我們可以給原型對象采取對象形式賦值.

但是這樣就會覆蓋構造函數原型對象原來的內容,這樣修改后的原型對象 constructor 就不再指向當前構造函數了

此時,我們可以在修改后的原型對象中,添加一個 constructor 指向原來的構造函數。

對象原型

構造函數創建實例對象和含有原型對象(prototype),實例對象的__proto__指向原型對象,實例對象的__protype__和原型對象的constructor指向構造函數。

對象都會有一個屬性 __proto__ 指向構造函數的 prototype 原型對象,之所以我們對象可以使用構造函數 prototype

原型對象的屬性和方法,就是因為對象有__proto__ 原型的存在。

注意:

  • __proto__是JS非標準屬性

  • [[prototype]]和__proto__意義相同

  • 用來表明當前實例對象指向哪個原型對象prototype

  • __proto__對象原型里面也有一個 constructor屬性,指向創建該實例對象的構造函數

原型繼承

繼承是面向對象編程的另一個特征,通過繼承進一步提升代碼封裝的程度,JavaScript 中大多是借助原型對象實現繼承

的特性。

龍生龍、鳳生鳳、老鼠的兒子會打洞描述的正是繼承的含義。

<body><script>// 繼續抽取   公共的部分放到原型上// const Person1 = {//   eyes: 2,//   head: 1// }// const Person2 = {//   eyes: 2,//   head: 1// }// 構造函數  new 出來的對象 結構一樣,但是對象不一樣function Person() {this.eyes = 2this.head = 1}// console.log(new Person)// 女人  構造函數   繼承  想要 繼承 Personfunction Woman() {}// Woman 通過原型來繼承 Person// 父構造函數(父類)   子構造函數(子類)// 子類的原型 =  new 父類  Woman.prototype = new Person()   // {eyes: 2, head: 1} // 指回原來的構造函數Woman.prototype.constructor = Woman// 給女人添加一個方法  生孩子Woman.prototype.baby = function () {console.log('寶貝')}const red = new Woman()console.log(red)// console.log(Woman.prototype)// 男人 構造函數  繼承  想要 繼承 Personfunction Man() {}// 通過 原型繼承 PersonMan.prototype = new Person()Man.prototype.constructor = Manconst pink = new Man()console.log(pink)</script>
</body>

原型鏈(查找規則)

基于原型對象的繼承使得不同構造函數的原型對象關聯在一起,并且這種關聯的關系是一種鏈狀的結構,我們將原型對象的鏈狀結構關系稱為原型鏈

<body><script>// function Objetc() {}console.log(Object.prototype)console.log(Object.prototype.__proto__)function Person() {}const ldh = new Person()// console.log(ldh.__proto__ === Person.prototype)// console.log(Person.prototype.__proto__ === Object.prototype)console.log(ldh instanceof Person)console.log(ldh instanceof Object)console.log(ldh instanceof Array)console.log([1, 2, 3] instanceof Array)console.log(Array instanceof Object)</script>
</body>

① 當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性。

② 如果沒有就查找它的原型(也就是__?proto__指向的 prototype 原型對象)

③ 如果還沒有就查找原型對象的原型(Object的原型對象)

④ 依此類推一直找到 Object 為止(null)

⑤ __proto__對象原型的意義就在于為對象成員查找機制提供一個方向,或者說一條路線

⑥ 可以使用 instanceof 運算符用于檢測構造函數的 prototype 屬性是否出現在某個實例對象的原型鏈上

六、深淺拷貝

只針對引用數據類型

1.淺拷貝

拷貝的是地址

常見方法:

(1)拷貝對象:Object.assgin()/展開運算符{…obj}拷貝對象

(2)拷貝數組:Array/ptotype.concat()或者{…arr}

2.深拷貝

拷貝的是對象,不是地址

2.1遞歸實現深拷貝

1.深拷貝實現拷貝出來的新對象不會影響舊對象?,通過函數遞歸實現

2.普通拷貝的話直接賦值就可以,遇到數組再次調用這個遞歸函數

3.如果遇到對象,就調用遞歸函數解決對象,【先array,后對象】??

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = {}// 拷貝函數function deepCopy(newObj, oldObj) {debuggerfor (let k in oldObj) {// 處理數組的問題  一定先寫數組 在寫 對象 不能顛倒if (oldObj[k] instanceof Array) {newObj[k] = []//  newObj[k] 接收 []  hobby//  oldObj[k]   ['乒乓球', '足球']deepCopy(newObj[k], oldObj[k])} else if (oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k], oldObj[k])}else {//  k  屬性名 uname age    oldObj[k]  屬性值  18// newObj[k]  === o.uname  給新對象添加屬性newObj[k] = oldObj[k]}}}deepCopy(o, obj) // 函數調用  兩個參數 o 新對象  obj 舊對象console.log(o)o.age = 20o.hobby[0] = '籃球'o.family.baby = '老pink'console.log(obj)console.log([1, 23] instanceof Object)// 復習// const obj = {//   uname: 'pink',//   age: 18,//   hobby: ['乒乓球', '足球']// }// function deepCopy({ }, oldObj) {//   // k 屬性名  oldObj[k] 屬性值//   for (let k in oldObj) {//     // 處理數組的問題   k 變量//     newObj[k] = oldObj[k]//     // o.uname = 'pink'//     // newObj.k  = 'pink'//   }// }</script>
</body>

2.2js庫lodash里面cloneDeep

<body><!-- 先引用 --><script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = _.cloneDeep(obj)console.log(o)o.family.baby = '老pink'console.log(obj)</script>
</body>

2.3JSON序列化

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}// 把對象轉換為 JSON 字符串// console.log(JSON.stringify(obj))const o = JSON.parse(JSON.stringify(obj))console.log(o)o.family.baby = '123'console.log(obj)</script>
</body>

七、異常處理

異常處理指預估代碼執行過程中可能發生的錯誤,然后最大程度的避免錯誤的發生導致整個程序無法繼續運行

throw拋異常

1、throw拋出異常信息后,程序也會終止執行

2、throw后面跟的是錯誤提示信息

3、Error對象配合throw使用,能夠設置更詳細的錯誤信息

<script>function counter(x, y) {if(!x || !y) {// throw '參數不能為空!';throw new Error('參數不能為空!')}return x + y}counter()
</script>

try/catch捕獲錯誤信息

  1. try...catch 用于捕獲錯誤信息

  2. 將預估可能發生錯誤的代碼寫在 try 代碼段中

  3. 如果 try 代碼段中出現錯誤后,會執行 catch 代碼段,并截獲到錯誤信息

<script>function foo() {try {// 查找 DOM 節點const p = document.querySelector('.p')p.style.color = 'red'} catch (error) {// try 代碼段中執行有錯誤時,會執行 catch 代碼段// 查看錯誤信息console.log(error.message)// 終止代碼繼續執行return}finally {//不管代碼報不報錯誤,仍然執行該行代碼alert('執行')}console.log('如果出現錯誤,我的語句不會執行')}foo()
</script>

debugger

八、處理this

1.普通函數this指向

誰調用就指向誰

嚴格模式下指向undefined

2.箭頭函數this指向

箭頭函數中的 this 與普通函數完全不同,也不受調用方式的影響,事實上箭頭函數中并不存在 this !箭頭函數中訪問的 this 不過是箭頭函數所在作用域的 this 變量

總結:1.函數內部不存在this,沿用上一級的this

2.不適用:構造函數、原型函數、dom事件函數等

3.適用:需要使用上層的this的地方

4.如果正確的話,它會在很多地方帶來方便。

3.改變this指向

(1)call

<script>// 普通函數function sayHi() {console.log(this);}let user = {name: '小明',age: 18}let student = {name: '小紅',age: 16}// 調用函數并指定 this 的值sayHi.call(user); // this 值為 usersayHi.call(student); // this 值為 student// 求和函數function counter(x, y) {return x + y;}// 調用 counter 函數,并傳入參數let result = counter.call(null, 5, 10);console.log(result);
</script>

總結:

  1. call方法能夠在調用函數的同時指定 this 的值

  2. 使用 call 方法調用函數時,第1個參數為 this 指定的值

  3. call 方法的其余參數會依次自動傳入函數做為函數的參數

(2)apply

總結:

  1. apply 方法能夠在調用函數的同時指定 this 的值

  2. 使用 apply 方法調用函數時,第1個參數為 this 指定的值

  3. apply 方法第2個參數為數組,數組的單元值依次自動傳入函數做為函數的參數

call和apply的區別是?

都是調用函數,都能夠改變this指向。但它們的參數不一樣,apply傳遞的必須是數組

(3)bind

不會調用函數,但是能改變this的指向

返回值是個函數,但是這個函數里面的this是更改過的obj

主要應用場景:

call調用函數并且可以傳遞參數

apply經常跟數組有關系,比如借助數學對象實現求最大值和最小值

bind不調用函數,但是還想改變this指向,比如改變定時器內部的this指向

九、防抖節流

防抖(debounce):

單位時間內,頻繁觸發事件,只執行最后一次

所謂防抖,就是指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間

使用場景:輸入手機號,郵箱驗證輸入檢測

節流(throttle):

單位時間內,頻繁出發事件,只執行一次

所謂節流,就是指連續觸發事件但是在 n 秒中只執行一次函數

使用場景:鼠標移動mousemove,頁面尺寸縮放resize、滾動條滾動scroll

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

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

相關文章

驅動開發硬核特訓 · Day 25 (附加篇):從設備樹到驅動——深入理解Linux時鐘子系統的實戰鏈路

一、前言 在嵌入式Linux開發中&#xff0c;無論是CPU、外設控制器&#xff0c;還是簡單的GPIO擴展器&#xff0c;大多數硬件模塊都離不開時鐘信號的支撐。 時鐘子系統&#xff08;Clock Subsystem&#xff09;&#xff0c;作為Linux內核中基礎設施的一部分&#xff0c;為設備…

并發設計模式實戰系列(7):Thread Local Storage (TLS)

&#x1f31f; 大家好&#xff0c;我是摘星&#xff01; &#x1f31f; 今天為大家帶來的是并發設計模式實戰系列&#xff0c;第七章Thread Local Storage (TLS)&#xff0c;廢話不多說直接開始~ 目錄 一、核心原理深度拆解 1. TLS內存模型 2. 關鍵特性 二、生活化類比&a…

時序數據庫 TDengine × Perspective:你需要的可視化“加速器”

你有沒有遇到這樣的場景&#xff1a;數據已經寫進數據庫&#xff0c;圖表卻總是“慢半拍”&#xff1f;或是操作界面太卡&#xff0c;光是一個排序就能讓你等到喝完一杯咖啡&#xff1f;當數據量越來越大、響應時間卻越來越長&#xff0c;開發者和用戶都不禁要問一句——就沒有…

前端面試每日三題 - Day 19

這是我為準備前端/全棧開發工程師面試整理的第十一天每日三題練習&#xff0c;涵蓋 JavaScript中WeakMap與內存管理的底層機制、Redux Toolkit的事件以及系統設計中的企業級表單引擎構建。通過這三道題&#xff0c;你將對現代前端開發中的關鍵概念有更深入的理解&#xff0c;并…

Antd Modal Drawer 更改默認項

當項目比較大使用了非常多的 Modal 和 Drawer 要是有需求一次性全部調整就會比較麻煩&#xff0c;目前 Antd 的 ConfigProvider 暫不支持&#xff08;也有可能我沒找到&#xff0c;待大佬指證&#xff09;就比如由于默認 Modal Drawer 的遮罩層是可以點擊關閉的&#xff0c;但是…

硬件工程師面試常見問題(8)

第三十六問&#xff1a;基爾霍夫定理的內容是什么&#xff1f; 基爾霍夫電流定理&#xff1a; 1. 內容&#xff1a;電路中任意一個節點上&#xff0c;在任意時刻&#xff0c;流入節電的電流之和等于流出節點的電流之和。 2. 表達式&#xff1a;根據上圖寫出節點電流定律的數學…

Elasticsearch 內存使用指南

作者&#xff1a;來自 Elastic Valentin Crettaz 探索 Elasticsearch 的內存需求以及不同類型的內存統計信息。 Elasticsearch 擁有豐富的新功能&#xff0c;幫助你為你的使用場景構建最佳搜索解決方案。瀏覽我們的示例筆記本了解更多信息&#xff0c;開始免費云試用&#xff0…

硬件工程師面試常見問題(9)

第四十一問&#xff1a;色環電阻的顏色表示什么&#xff1f; 各環表示的意思&#xff1a; 4色環的&#xff1a;前兩位表示有效位&#xff1b;第三環表示倍乘&#xff1b;最后一環表示誤差&#xff1b; 5色環的&#xff1a;前三位表示有效位&#xff1b;第四環表示倍乘&#…

PyTorch 深度學習實戰(23):多任務強化學習(Multi-Task RL)之擴展

之前的PyTorch 深度學習實戰&#xff08;23&#xff09;&#xff1a;多任務強化學習&#xff08;Multi-Task RL)總結擴展運用代碼如下&#xff1a; import torch import torch.nn as nn import torch.optim as optim import numpy as np from torch.distributions import Norm…

前端——CSS1

一&#xff0c;概述 CSS&#xff08;Cascading Style Sheets&#xff09;&#xff08;級聯樣式表&#xff09; css是一種樣式表語言&#xff0c;為html標簽修飾定義外觀&#xff0c;分工不同 涉及&#xff1a;對網頁的文字、背景、寬、高、布局進行修飾 分為內嵌樣式表&…

賦能航天教育:高校衛星仿真教學實驗平臺解決方案

?????? 隨著全球航天事業的飛速發展&#xff0c;對高素質航天人才的需求日益增長。如何在高校階段提前鍛煉學生的航天工程實踐能力&#xff0c;成為教育界的重要命題。作為領先的通信與網絡技術供應商&#xff0c;IPLOOK基于自身在5G核心網、衛星通信及仿真平臺領域的深…

Python爬蟲(10)Python數據存儲實戰:基于pymongo的MongoDB開發深度指南

目錄 一、為什么需要文檔型數據庫&#xff1f;1.1 數據存儲的范式變革1.2 pymongo的核心優勢 二、pymongo核心操作全解析2.1 環境準備2.2 數據庫連接與CRUD操作2.3 聚合管道實戰2.4 分批次插入百萬級數據&#xff08;進階&#xff09;2.5 分批次插入百萬級數據&#xff08;進階…

Springboot 手搓 后端 滑塊驗證碼生成

目錄 一、效果演示 二、后端滑塊驗證碼生成思路 三、原理解析 四、核心代碼拿走 滑塊驗證碼react前端實現&#xff0c;見我的這篇博客&#xff1a;前端 React 彈窗式 滑動驗證碼實現_react中使用阿里云滑塊驗證碼2.0前端接入及相關視覺-CSDN博客 一、效果演示 生成的案例…

關于flink兩階段提交高并發下程序卡住問題

先拋出代碼 package com.dpf.flink;import com.dpf.flink.sink.MysqlSink; import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.…

html css js網頁制作成品——HTML+CSS+js美甲店網頁設計(5頁)附源碼

美甲店 目錄 一、&#x1f468;?&#x1f393;網站題目 二、??網站描述 三、&#x1f4da;網站介紹 四、&#x1f310;網站效果 五、&#x1fa93; 代碼實現 &#x1f9f1;HTML 六、&#x1f947; 如何讓學習不再盲目 七、&#x1f381;更多干貨 一、&#x1f468;?&a…

LeetCode[347]前K個高頻元素

思路&#xff1a; 使用小頂堆&#xff0c;最小的元素都出去了&#xff0c;省的就是大&#xff0c;高頻的元素了&#xff0c;所以要維護一個小頂堆&#xff0c;使用map存元素高頻變化&#xff0c;map存堆里&#xff0c;然后輸出堆的東西就行了 代碼&#xff1a; class Solution…

2024年網站開發語言選擇指南:PHP/Java/Node.js/Python如何選型?

2024年網站開發語言選擇指南&#xff1a;PHP/Java/Node.js/Python如何選型&#xff1f; 一、8大主流Web開發語言技術對比 1. PHP開發&#xff1a;中小型網站的首選方案 最新版本&#xff1a;PHP 8.3&#xff08;2023年11月發布&#xff09;核心優勢&#xff1a; 全球78%的網站…

從數據結構說起(一)

1 揭開數據結構神奇的面紗 1.1 初識數據結構 在C的標準庫模板&#xff08;Standard Template Library,STL&#xff09;課程上&#xff0c;我初次結識了《數據結構》。C語言提供的標準庫模板是面向對象程序設計與泛型程序設計思想相結合的典范。所謂的泛型編程就是編寫不依賴于具…

JAVA--- 關鍵字static

之前我們學習了JAVA 面向對象的一些基本知識&#xff0c;今天來進階一下&#xff01;&#xff01;&#xff01; static關鍵字 static表示靜態&#xff0c;是JAVA中的一個修飾符&#xff0c;可以修飾成員方法&#xff0c;成員變量&#xff0c;可用于修飾類的成員&#xff08;變…

4.27比賽總結

文章目錄 T1T2法一&#xff1a;倍增求 LCA法二&#xff1a;Dijkstra 求最短路法三&#xff1a;dfs 求深度 T3T4總結 T1 一道非常簡單的題&#xff0c;結果我因為一句話沒寫掛了 80pts…… 題目中沒寫 a a a 數組要按照 b b b 數組的順序&#xff0c;所以對于最大方案&#x…