前言
為了鞏固自己的知識和提升技術堆疊的廣度以及深度,每天都會學習一道面試題(本文會持續更新)
如何獲取陣列中最大的數 (2020/11/27)
1.排序法
const arr = [1, 2, 3, 4, 5, 6];
arr.sort((a, b) => {
return b - a;
});
const max = arr[0];
console.log(max); // 輸出最大值 6
2.假設法
const arr = [2, 1, 3, 5, 4, 6];
for (let i = 1; i < arr.length; i++) {
max = arr[0];
const cur = arr[i];
cur > max ? (max = cur) : max;
}
console.log(max); // 輸出最大值 6
3.內置 Max()方法
/**
* 內置函式Math.max()支持傳遞多個引數,但不支持直接傳遞一個陣列,所以需要借助apply()來傳遞一個陣列,
*
* apply()與call()方法類似,區別在于apply()接受的是引數陣列,call()接受的是引數串列,
*/
const arr = [1, 2, 3, 4, 5, 6];
const max = Math.max.apply(null, arr);
console.log(max); // 輸出最大值 6
4.ES6 擴展運算子
const arr = [1, 2, 3, 4, 5, 6];
console.log(Math.max(...arr)); // 輸出最大值 6
什么是虛擬 DOM (2020/11/28)
DOM 樹是對 HTML 的抽象,VDOM 就是對真實 DOM 樹的抽象,VDOM 不會觸及瀏覽器的部分,只是存在于 Javascript 空間的樹形結構,
虛擬 DOM(VDOM)是真實 DOM 的記憶體表示,一種編程概念,一種模式,它會和真實的 DOM 同步,在更新 DOM 樹時,虛擬 DOM 使用 diff 演算法對比新舊 DOM 的變化,實作區域更新,節省了瀏覽器性能,
DNS 如何進行決議 (2020/11/29)
-
DNS(Domain Name System): "域名系統"的英文縮寫,是互聯網上作為域名和 IP 地址相互映射的一個分布式資料庫,它用于 TCP/IP 網路,它所提供的服務是用來將主機名和域名轉換為 IP 地址的作業,
-
域名決議: 通過域名,最終得到該域名對應的 IP 地址的程序就是域名決議,
DNS 實體決議:
1.打開瀏覽器,輸入一個域名(例如輸入www.4399.com),發出一個 DNS 請求到本地 DNS 服務器(中國電信等網路連接服務商提供),
2.本地 DNS 服務器查詢 DNS 請求是否存在快取記錄,存在,回傳結果;不存在,則本地 DNS 服務器向 DNS 根服務器(隨機根服務器d.root.servers.net)發送查詢請求,
3.DNS 根服務器(DNS 根服務器不記錄存盤具體的域名和 IP 的映射關系)回傳域服務器地址,
4.根據回傳結果,本地 DNS 服務器向域服務器(回傳對應域服務器地址c.gtld.servers.net)發送查詢請求,
5.域服務器(域服務器不會直接回傳域名與 IP 的映射關系)回傳本域名的決議服務器地址,
6.根據回傳結果,本地 DNS 服務器向域名的決議服務器(例如: .4399.com域服務器)發送查詢請求,
7.域名的決議服務器回傳請求域名對應的 IP 地址(例如: 116.207.132.239),
8.根據回傳結果,本地 DNS 服務器向客戶端回傳具體 IP 地址,并將查詢結果快取在本地 DNS 服務器中,加速下次客戶端的訪問,
如何獲取圖片原始尺寸資訊 (2020/11/30)
/**
* naturalWidth && naturalHeight 不兼容IE6/7/8
*/
getImageOriginal = () => {
let img = document.getElementById("bg-img");
const width = img.naturalWidth;
const height = img.naturalHeight;
};
React 類組件和函陣列件的區別 (2020/12/01)
-
類組件: 擁有更多的特性,擁有 state 狀態和生命周期鉤子,
-
函陣列件: 單純接受 props 引數,是一個無狀態組件,
隨著 Hooks 的產生,函陣列件也可以擁有自身的 state 狀態,雖然 Hooks 解決了函陣列件 state 的問題,使得代碼更加簡潔輕便,但是類組件還是擁有著函陣列件沒有的其他特性,
什么是 JSX (2020/12/02)
下面例子的標簽語法是 JSX 語法,
/**
* JSX 是一個 Javascript 的語法擴展,既不是字串也不是 HTML,具有 Javascript 的全部功能,
*
* JSX 語法中,可以在大括號中放置任何有效的 Javascript 運算式,
*
* JSX 也是一個運算式,可以賦值給變數、也可以作為引數傳入函式,
*/
const element = <h1>Hello, World!</h1>;
React 中 state 和 props 有什么區別 (2020/12/03)
相同點:
React 組件的資料分為兩種,props 和 state,兩個資料的改變,都可能會引發組件重新渲染,
(props 和 state 可以保存資訊,資訊可以控制組件的渲染輸出)
區別:
1.props 是組件的對外介面;state 是組件的內部狀態,
2.props 是傳遞給組件的(類似于函式的形參);state 是在組件內被組件自己管理的(類似于在一個函式內宣告的變數),
3.props 是不可修改的,所有 React 組件都必須像純函式一樣保護它們的 props 不被修改;state 是多變的、可以修改的,每次 setState 都會異步更新,
什么時候應該選擇 Class 實作一個組件,什么時候應該選擇一個函式實作一個組件 (2020/12/04)
Class 類組件: 擁有自身 state 狀態管理,擁有生命周期方法,繼承 ReactComponent 實體化,
無狀態的函陣列件: 函陣列件沒有鏈接到 ReactComponent 實體的 this 屬性和生命周期方法,
原則一: 如果你的組件需要訪問 this 就用 Class 實作組件,
原則二: 如果你的組件需要生命周期方法,使用 Class 實作組件,
黃金原則: 如果你可以使用無狀態組件,那就使用函式實作一個組件,
總結:
-
如果可以使用無狀態函式,就是盡管用函式,
-
否則,就使用 Class 類,
setState 可以接受函式為引數嗎? 有什么作用 (2020/12/05)
setState 函式的弊端: setState 不會立刻改變(更新)React 組件中的 state 值(產生的效果不直觀),
作用: 函式式的 setState 可以解決 setState 存在的弊端,讓 setState 函式產生的結果更直觀有效,函式接收兩個引數,第一個是當前的 state 值,第二個是當前的 props 值,函式應該回傳一個物件(代表要對 this.setState 的更改),
// 函式式 setState
class Counter extends React.Component {
state = { count: 0 };
handleIncrement = () => {
this.setState((state, props) => {
return {
count: state.count + 1,
};
});
};
render() {
const { count } = this.state;
return (
<div>
<button onClick={this.handleIncrement}>+++</button>
<span>{count}</span>
</div>
);
}
}
描述一下 React 組件的各個生命周期函式 (2020/12/06)
React 組件的生命周期分為三個部分: 裝載期(Mounting)、更新期(Updating)、卸載期(Unmounting),
1.裝載期(組件第一次在 DOM 樹中渲染的程序)
裝載期呼叫函式順序:
/**
* constructor(創造一個組件的實體,呼叫對應的建構式)
*
* getInitialState(初始化組件的內部狀態this.state) && getDefaultProps(初始化外部介面props)
*
* componentWillMount(在render函式之前呼叫,可以在服務端呼叫、也可以在瀏覽器端呼叫)
*
* render(回傳一個JSX描述結構的純函式)
*
* componentDidMount(在render函式之后呼叫,函式呼叫時,render函式回傳的結構已經渲染、組件已經"裝載"到DOM樹中;只能在瀏覽器端呼叫)
*/
2.更新期(組件被重新渲染的程序)
更新期呼叫函式順序:
/**
* componentWillReceiveProps(nextProps): 只要是父組件的render函式被呼叫,render函式里子組件就會更新,
* 不管props變與不變,都會觸發該函式,通過this.setState方法觸發的更新程序不會呼叫這個函式,
*
* shouldComponentUpdate(nextProps, nextState): 決定一個組件什么時候不需要渲染,回傳一個布林值,true,render重新渲染;false,render不需要渲染,
*
* componentWillUpdate(在render函式之前呼叫,只有在瀏覽器端呼叫)
*
* render(渲染純函式,決定了渲染什么)
*
* componentDidUpdate(prevProps, prevState): 在render函式之后呼叫,可以在服務端呼叫,也可以在瀏覽器端呼叫,
*/
3.卸載期(組件從 DOM 中洗掉的程序)
卸載期:
/**
* componentWillUnmount(React組件要從DOM樹中洗掉前,呼叫卸載函式): componentWillUnmount 中的作業與 componentDidMount相關聯,
*
* componenWillUnmount可以清理React組件生產的記憶體垃圾,避免造成記憶體泄漏,
*/
什么是 shouldComponentUpdate 函式? 有什么作用 (2020/12/07)
shouldComponentUpdate 函式是 React 組件生命周期中更新期的一個具有高性能、決定性的函式,在更新程序中,React 組件首先呼叫 shouldComponentUpdate 函式,如果函式回傳 true,就繼續更新程序(render 函式);回傳 false,就立刻終止更新程序,不會觸發后續更新渲染,
作用:
1.shouldComponentUpdate 函式回傳一個布林值,告知 React 組件在更新程序中是否要繼續更新,
2.shouldComponentUpdate 函式使用恰當,可以大大提高 React 組件的性能,
當組件的 setState 函式被呼叫之后,會發生什么 (2020/12/08)
setState 函式呼叫后觸發組件更新,頁面重新繪制,根據生命周期中的更新期,setState 函式不會呼叫 componentWillReceiveProps 函式,但是其余的更新函式呼叫不變,
/**
* shouldComponentUpdate(當shouldComponentUpdate函式被呼叫的時候,this.state沒有得到更新)
*
* componentWillUpdate(當componentWillUpdate函式被呼叫的時候,this.state依然沒有得到更新)
*
* render(直到render函式被呼叫的時候,this.state才得到更新)
*
* componentDidUpdate()
*/
什么是 Fiber? 是為了解決什么問題 (2020/12/09)
Fiber 是更新程序碎片化的資料結構(每執行完一段更新程序,就把控制權交還React負責任務協調的模塊,比對是否有新的緊急的任務需要更新,有,則優先更新緊急任務;無,則回到節點繼續更新剩余任務),
解決問題:
在 16.0 版本之前的 React 中,更新程序是同步的一層組件套一層組件,逐漸深入的程序,在更新完所有組件之前不會停止,呼叫時長長,而 Javascript 具有單執行緒的特點,每個同步任務時長不能太長,時長過長會對其他的輸入的回應削弱甚至無回應,React Fiber 就是為了解決同步操作時長過長導致的性能問題,
什么是 HoC(Higher-Order Component)? 適用于什么場景 (2020/12/10)
HOC 高階組件: 接受一個組件作為輸入,回傳一個新組件作為結果的函式,
import React from 'react';
function wrapperComponent(wrappedComponent) {
return class WrappingComponent extends React.Component {
render() {
const {id, ...props} = this.props;
return <WrappedComponent {...props}>
}
}
}
export default wrapperComponent;
使用場景:
1.重用代碼: 有時一個功能邏輯會在多處 React 組件中使用,利用高階組件的方式把這部分公用邏輯提取出來,就可以減少組件代碼的重復使用率,
2.修改現有 React 組件的行為: 對于一些高度封裝的 React 組件(第三方組件或團隊內自己封裝好的組件),對這一類 React 組件進行二次開發時,不想改動封裝組件內部邏輯,利用高階組件的方式就可以基于原有的組件函式產生新的組件,這樣就不會對原有的組件產生任何改動,保證專案代碼運行正常,
為什么我們利用回圈產生的組件中要用上 key 這個特殊的 prop (2020/12/11)
在 React 組件中,回圈渲染的組件需要加上 key 屬性,沒有 key 時,React 會發出警告(a key should be provided for list items),告知我們組件必須要有 key 屬性,
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((item, index) => {
return <li key={item.toString()}>{item}</li>;
});
return (
<div>
<ul>{listItems}</ul>
</div>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById("root")
);
key 的作用: key 屬性幫助 React 識別元素,確定元素的增刪查改;在回圈渲染的組件中,可以根據特定的 key 值,對相應的組件做特別的操作處理等,
let 與 const 有什么區別 (2020/12/12)
相似:
- 都是只在宣告所在的塊級作用域內有效,
- 都不能在所在作用域內有相同名稱的變數和函式,
區別:
- const 宣告的變數(常量)必須初始化;let 宣告的變數不用初始化,
- const 宣告的變數(常量)不可以賦值改變;let 宣告的變數可以改變,值和型別都可以改變,沒有限制,
什么是 React Hooks? (2020/12/13)
Hooks 是 React 16.8 中添加的一個全新的 API,它可以讓你在不撰寫 class 的情況下使用 state 以及其他的 React 特性,React Hooks 的意思是,組件盡量寫成純函式,如果需要外部功能和副作用,就用鉤子把外部的代碼"鉤"進來,React Hooks 就是那些鉤子,你需要什么功能,就是用什么鉤子,React 默認提供了一些常用的鉤子,或者也可以使用封裝屬于自己的鉤子,所有的鉤子都是為函式引入外部功能,所以 React 約定,鉤子一律使用use前綴命名,
React Hooks 使用規則是什么? (2020/12/14)
Hooks 就是 Javascript 函式,但是使用它們會有兩個額外的規則:
-
只能在函式最外層呼叫 Hooks,不要再回圈、條件判斷或者子函式中呼叫,
-
只能在React 的函式組件中呼叫 Hooks,不要在其他 Javascript 函式中呼叫,
簡述 Flux 思想 (2020/12/15)
一個 Flux 包含四個部分:
-
Dispatcher: 處理動作分發,維持 Store 之間的依賴關系,
-
Store: 負責存盤資料和處理資料相關邏輯,
-
Action: 驅動 Dispatcher 的 Javascript 物件,
-
View: 視圖部分,負責顯示用戶界面,
Flux 的好處,最重要的就是"單向資料流"的管理方式,在 Flux 的理念中,如果要改變界面,必須改變 store 中的狀態;如果要改變 store 中的狀態,必須派發一個 action 物件,
Flux 流程:
1.用戶訪問 View
2.View 發出用戶指定的 Action,
3.Dispatcher 收到 Action,要求 Store 進行相應的更新,
4.Store 更新后,發出一個"change"事件,
5.View 收到"change"事件后,更新頁面,
options 請求方法有什么用 (2020/12/16)
options 請求方法的主要用途有兩個:
1.獲取服務器支持的 HTTP 請求方法,
2.用來檢查服務器的性能(形如: AJAX進行跨域請求時的預檢,需要向另外一個域名的資源發送一個HTTP OPTIONS請求頭,用以判斷實際發送的請求是否安全),
簡述 https 原理,以及與 http 的區別 (2020/12/17)
HTTPS 原理:
1.客戶端(Client)發起一個 HTTPS 的請求,
2.服務端(Server)把事先配置好的公鑰證書回傳給客戶端,
3.客戶端驗證公鑰證書有效性,驗證通過則繼續;不通過則顯示警告資訊,
4.客戶端使用偽亂數生成器生成加密所使用的對稱密鑰,然后使用證書的公鑰加密這個對稱密鑰,發送給服務端,
5.服務端使用自己的私鑰解密這個訊息,獲得密鑰,
6.服務端使用獲得的對稱密鑰加密"明文內容 A",發送給客戶端,
7.客戶端使用對稱密鑰解密回應的密文,得到"明文內容 A",
8.客戶端再次發起 HTTPS 請求,使用對稱密鑰加密請求的"明文內容 B",
9.服務端使用之前獲得的對稱密鑰解密密文,得到"明文內容 B",
區別:
1、https 協議需要到 ca 申請證書,一般免費證書較少,因而需要一定費用,
2、http 是超文本傳輸協議,資訊是明文傳輸,https 則是具有安全性的 ssl 加密傳輸協議,
3、http 和 https 使用的是完全不同的連接方式,用的埠也不一樣,前者是 80,后者是 443,
4、http 的連接很簡單,是無狀態的;HTTPS 協議是由 SSL+HTTP 協議構建的可進行加密傳輸、身份認證的網路協議,比 http 協議安全,
實作陣列扁平化 (2020/12/18)
1.flat() 方法
const arr = [[1, 2], [3, 4], 5, 6];
console.log(arr.flat()); // 輸出: [1,2,3,4,5,6]
2.reduce() 與 concat() 方法
const arr = [[1, 2], [3, 4], 5, 6];
console.log(arr.reduce((acc, val) => acc.concat(val), [])); // 輸出: [1,2,3,4,5,6]
3.擴展運算子
const arr = [[1, 2], [3, 4], 5, 6];
console.log([].concat(...arr)); // 輸出: [1,2,3,4,5,6]
4.正則式
const arr = [[1, 2], [3, 4], 5, 6];
const results = JSON.parse(
"[" + JSON.stringify(arr).replace(/\[|\]/g, "") + "]"
);
console.log(results); // 輸出: [1,2,3,4,5,6]
實作陣列去重 (2020/12/19)
1.ES6 Set() 方法
const arr = [1, 3, 2, 4, 3, 1, 5, 2];
console.log([...new Set(arr)]); // 輸出: [1,3,2,4,5]
2.兩層 for 回圈 + splice()
const arr = [1, 3, 2, 4, 3, 1, 5, 2];
function unique(arr) {
let length = arr.length;
for (let i = 0; i < length; i++) {
for (let j = i + 1; j < length; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
length--;
j--;
}
}
}
return arr;
}
const results = unique(arr);
console.log(results); // 輸出: [1,3,2,4,5]
3.indexOf() 方法
const arr = [1, 3, 2, 4, 3, 1, 5, 2];
const unique = (arr) => {
let results = [];
for (let i = 0; i < arr.length; i++) {
if (results.indexOf(arr[i]) === -1) {
results.push(arr[i]);
}
}
return results;
};
console.log(unique(arr)); // 輸出: [1,3,2,4,5]
4.includes() 方法
const arr = [1, 3, 2, 4, 3, 1, 5, 2];
const unique = (arr) => {
let results = [];
for (let i = 0; i < arr.length; i++) {
if (!results.includes(arr[i])) {
results.push(arr[i]);
}
}
return results;
};
console.log(unique(arr)); // 輸出: [1,3,2,4,5]
你知道那些 http 頭部 (2020/12/20)
HTTP 頭域包括通用頭、請求頭、回應頭和物體頭,每個頭域由域名、冒號、域值組成,
1.通用頭部是客戶端和服務端都可以使用的頭部,可以在客戶端、服務端和其他應用程式之間提供一些非常有用的通用功能,如 Date 頭部,
2.請求頭部是請求報文特有的,它們為服務器提供了一些額外資訊,比如客戶端希望接收什么型別的資料,如 Accept 頭部,
3.回應頭部便于客戶端提供資訊,比如,客服端在與哪種型別的服務器進行互動,如 Server 頭部,
4.物體頭部指的是用于應對物體主體部分的頭部,比如,可以用物體頭部來說明物體主體部分的資料型別,如 Content-Type 頭部,
實作深淺拷貝 (2020/12/21)
1.淺拷貝: 如果陣列元素是基本型別,拷貝一份,互不影響;而如果陣列元素是物件或者陣列,就會拷貝物件和陣列的參考,這樣原陣列(物件)和新陣列(物件)都會改變的復制參考拷貝方法稱為淺拷貝,陣列的concat(),slice()方法就是一種淺拷貝,
const arr = [1, 2, { name: "tom" }];
const newArr = arr.concat();
arr[2].name = "jerry";
console.log(arr); // 輸出 [1,2,{name:'jerry'}]
console.log(newArr); // 輸出 [1,2,{name:'jerry'}]
實作淺拷貝:
function shallowCopy(obj) {
if (typeof obj != "object") return; // 判斷傳入的引數,確保拷貝的只有物件
let newObj = obj instanceof Array ? [] : {}; // 判斷引數obj型別,新建陣列或者物件
// 遍歷obj,判斷是obj的屬性才拷貝
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
2.深拷貝: 完全的拷貝一個物件和陣列,原陣列(物件)和新陣列(物件)兩者相互分離,兩者之間的修改完全獨立且不會相互影響,這樣的復制參考拷貝方法稱為深拷貝,JSON.stringify()方法就是一種深拷貝,
const arr = [1, 2, { name: "tom" }];
const newArr = JSON.parse(JSON.stringify(arr));
arr[2].name = "jerry";
console.log(arr); // 輸出 [1,2,{name:'jerry'}]
console.log(newArr); // 輸出 [1,2,{name:'tom'}]
實作深拷貝:
function deepCopy(obj) {
if (typeof obj != "object") return;
let newObj = obj instanceof Array ? [] : {};
// 判斷屬性值的型別,如果是物件,遞回呼叫深拷貝函式
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] =
typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
實作函式柯里化 (2020/12/22)
柯里化: 一種將使用多個引數的一個函式轉換成一系列使用一個引數的函式的技術(將一個接受多個引數的函式變為接受一個引數回傳一個函式的固定形式),
實作柯里化:
function curry() {
const _args = [...arguments];
function fn() {
_args.push(...arguments);
return fn;
}
fn.toString = function () {
return _args.reduce((sum, cur) => sum + cur);
};
return fn;
}
實作判斷一個型別的方法,可以區分 Null 與 Object (2020/12/23)
typeof 是一元運算子,可以對資料型別進行判斷,回傳值是表示運算元型別的一個字串,但是 Javascript 的資料型別中,Null 和 Object 的 typeof 都回傳 object字串,難以區分兩者資料型別;為了更好的去區分兩者之間的關系,可以使用 Object.prototype.toString 來檢驗兩者的區分,
var class2type = {};
// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error Null Undefined"
.split(" ")
.map(function (item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
});
function type(obj) {
// 兼容IE6
if (obj === null) {
return obj + "";
}
// 基本型別使用typeof,參考型別使用Object.prototype.toString
return typeof obj === "object" || obj === "function"
? class2type[Object.prototype.toString.call(obj)] || "object"
: typeof obj;
}
實作防抖節流 (2020/12/24)
防抖: 觸發高頻時間后 N 秒內函式只會執行一次,如果 N 秒內高頻時間再次觸發,則重新計算時間,防抖常用于用戶進行搜索輸入節約請求資源......
const debounce = (fn, time) => {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, time);
};
};
節流: 高頻時間觸發,但 N 秒內只會執行一次,所以節流會稀釋函式的執行頻率,節流常用于滑鼠不斷點擊觸發、監聽滾動事件......
const throttle = (fn, time) => {
let flag = true;
return function () {
if (!flag) {
return;
}
flag = false;
setTimeout(() => {
fn.apply(this, time);
flag = true;
}, time);
};
};
檢查重復字串 (2020/12/25)
1.方法一: 正則式判斷
/**
* 1.利用()進行分組,
*
* 2.利用/加數字表示參考,例如: /1就是參考第一個分組,
*
* 思路: 將[a-zA-Z]做分組,參考分組進行判斷是否有連續重復,
*/
const str = "hello";
const str1 = "tom";
function isRepeatStr(str) {
return /([a-zA-Z])\1/.test(str);
}
const res = isRepeatStr(str);
const res1 = isRepeatStr(str1);
console.log(res); // 輸出 true
console.log(res1); // 輸出 false
2.方法二: 字串
/**
* charAt(): 從一個字串中回傳指定的字符,
*/
const str = "hello";
const str1 = "tom";
function isRepeatStr(str) {
let reg = /[a-zA-Z]/;
for (let i = 0; i < str.length; i++) {
if (str.charAt(i) == str.charAt(i + 1) && reg.test(str[i])) {
return true;
}
}
return false;
}
const res = isRepeatStr(str);
const res1 = isRepeatStr(str1);
console.log(res); // 輸出 true
console.log(res1); // 輸出 false
call()、apply()、bind()的區別 (2020/12/26)
1.call() 和 apply() 改變了函式的 this 背景關系后便執行該函式,bind() 則是回傳改變了背景關系后的一個函式,
2.call() 和 apply() 的第一個引數都是要改變背景關系的物件,call() 第二個引數以引數串列的形式展現;apply() 第二個引數則是以引數陣列的形式展現,
/**
* call()語法:
* fun.call(thisArg, arg1, arg2,......)
* thisArg: 函式運行時指向的this值,
* arg1,arg2......: 系結函式呼叫時傳入的引數串列,
*/
/**
* apply()語法:
* apply(thisArg, [argsArray])
* thisArg: 函式運行時指向的this值,
* [argsArray]: 系結函式呼叫時傳入的引數陣列,
*/
/**
* bind()語法:
* bind(thisArg[, arg1[, arg2[, ......]]])
* thisArg: 函式運行時原函式指向的this值,
* [, arg1[, arg2[, ......]]]: 系結函式呼叫時傳入的引數,
*/
區別總結: 函式需要改變 this 指向時使用 call()、apply()、bind(),
- 傳遞引數不多,使用
call(thisArg, ...args), - 傳遞引數較多,使用
apply(thisArg, [...args]), - 生成一個新函式長期系結某個函式的某個物件使用,使用
bind(thisArg, ...args),
實作 add(1)(2)(3) (2020/12/27)
function add(...args) {
return args.reduce((a, b) => a + b);
}
function currying(fn) {
let args = [];
return function temp(...newArgs) {
if (newArgs.length) {
args = [...args, ...newArgs];
return temp;
} else {
let value = https://www.cnblogs.com/BlueBerryCode/archive/2020/12/29/fn.apply(this, args);
args = [];
return value;
}
};
}
let addCurry = currying(add);
console.log(addCurry(1)(2)(3)()); // 輸出 6
HTTP 狀態碼有哪些,分別代表什么意思? (2020/12/28)
HTTP 狀態碼:
1xx:指示資訊類,表示請求已接受,繼續處理,
2xx:指示成功類,表示請求已成功接受,
3xx:指示重定向,表示要完成請求必須進行更近一步的操作,
4xx:指示客戶端錯誤,請求有語法錯誤或請求無法實作,
5xx:指示服務器錯誤,服務器未能實作合法的請求,
常見的狀態碼:
200 OK:客戶端請求成功
206 Partial Content:客戶發送了一個帶有Range頭的GET請求,服務器完成了它(當時音頻或視頻檔案很大時回傳206)
301 Moved Permanently:所請求的頁面已經轉移至新的URL
302 Found:所請求的頁面已經臨時轉移至新的URL
304 Not Modified:客戶端有緩沖的檔案并發出看一個條件性的請求,服務器告訴客戶,原來緩沖的檔案還可以繼續使用
403 Forbidden:對請求頁面的訪問被禁止
404 Not Found:請求資源不存在
500 Internal Server Error:服務器發生不可預期的錯誤原來緩沖的檔案還可以繼續使用
503 Server Unavailable:請求未完成,服務器臨時過載或宕機,一段時間后可恢復正常
瀏覽器輸入 url 后發生了什么? (2020/12/29)
/**
* 大致流程:
*
* 1.url決議: 瀏覽器輸入url,判斷輸入的url是否是一個合法的url;同時檢查瀏覽器是否存在相對應的快取,存在,回傳快取并渲染頁面;不存在,則發送DNS請求,
*
* 2.DNS域名決議: 瀏覽器向DNS服務器請求決議輸入url對應的IP地址,回傳決議的IP地址給客戶端,
*
* 3.建立TCP連接: 接收決議好的IP地址,根據IP地址和默認埠80,和服務器建立TCP連接,
*
* 4.發送HTTP請求: 瀏覽器發出讀取檔案的HTTP請求,
*
* 5.服務器處理請求: 服務器對瀏覽器HTTP請求做出回應,回傳相對應的HTML文本給瀏覽器,
*
* 6.關閉TCP連接: 釋放關閉TCP連接,
*
* 7.瀏覽器決議HTML,渲染頁面: 瀏覽器接收服務器回傳的HTML文本,決議HTML文本內容渲染頁面,
*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/242291.html
標籤:其他
