1.symbol類型
Symbol 是 ECMAScript 6 中引入的一種新的基本數據類型,它表示獨一無二的值。Symbol 值是通過 Symbol()
函數創建的。
Symbol 值具有以下特點:
- 獨一無二性(唯一性):每個通過
Symbol()
函數創建的 Symbol 值都是唯一的,即使創建時傳入相同的參數也不會相等。 - 不可改變性:Symbol 值一經創建就不可改變,不能添加屬性或修改屬性值。
- 作為屬性名的唯一性:Symbol 值可以作為對象屬性的鍵名(屬性名),并且不會與其他屬性名產生沖突。
- 隱藏性:Symbol 值不會出現在
for...in
、for...of
循環中,也不會被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
等方法返回,但是可以通過Object.getOwnPropertySymbols()
方法獲取。
// 創建一個 Symbol 值
const mySymbol = Symbol();// 創建一個帶描述的 Symbol 值
const mySymbolWithDescription = Symbol('This is a symbol');// Symbol 值作為屬性名
const obj = {[mySymbol]: 'value'
};console.log(obj[mySymbol]); // 輸出 'value'// 獲取所有 Symbol 屬性
const symbolProperties = Object.getOwnPropertySymbols(obj);
console.log(symbolProperties); // 輸出 [Symbol()]// 使用全局 Symbol 注冊表
const symbol1 = Symbol.for('symbolKey');
const symbol2 = Symbol.for('symbolKey');
console.log(symbol1 === symbol2); // 輸出 true,因為它們在全局 Symbol 注冊表中具有相同的鍵
?2.模版字面量
模板字面量使用反引號()來界定字符串,并可以在字符串中使用
${}` 語法插入變量或表達式。以下是模板字面量的基本語法
const name = 'Alice';
const age = 30;// 使用模板字面量創建字符串
const message = `Hello, my name is ${name} and I am ${age} years old.`;console.log(message); // 輸出 "Hello, my name is Alice and I am 30 years old."const name = 'Alice';
const age = 30;// 嵌套使用模板字面量
const message = `Hello, my name is ${name} and I am ${age} years old.Today is a ${new Date().toLocaleDateString()}.
`;console.log(message);
3.defer和async的區別(DOMContentLoaded
是一個 DOM 事件,表示 HTML 文檔已經完全加載并解析完成,但不包括外部資源(例如圖片、樣式表、嵌入的框架等)的加載。)
當瀏覽器加載 HTML 并遇到<script>...</script>
標簽時,它無法繼續構建 DOM。它必須立即執行腳本。外部腳本<script src="..."></script>
也是如此:瀏覽器必須等待腳本下載,執行下載的腳本,然后才能處理頁面的其余部分。
這導致一個重要問題:
- 如果頁面頂部有一個龐大的腳本,它會“阻塞頁面”。在下載并運行之前,用戶無法看到頁面內容
有一個解決方法,就是把腳本放到最底部。(但是對于長 HTML 文檔,這可能會有明顯的延遲。)
defer屬性告訴瀏覽器不要等待腳本,瀏覽器會繼續處理 HTML,構建 DOM。該腳本“在后臺”加載,然后在 DOM 完全構建完成后再運行。defer腳本總是在 DOM 準備好時執行(但在DOMContentLoaded事件之前)defer腳本保持相對順序來執行
async屬性意味著該腳本是完全獨立的:
瀏覽器不會阻止async腳本
其他腳本也不會等待async腳本,async腳本也不會等待其他腳本
DOMContentLoaded和async腳本不會互相等待DOMContentLoaded可能在async腳本執行之前觸發(如果async腳本在頁面解析完成后完成加載)
或在async腳本執行之后觸發(如果async腳本很快加載完成或在 HTTP 緩存中)
簡單來說就是 async 腳本在后臺加載完就立即運行
注意:async和defer屬性都僅適用于外部腳本,如果script標簽沒有src屬性,盡管寫了async、defer屬性也會被忽略
4.函數柯里化
函數柯里化(curry)是函數式編程里面的概念。curry的概念很簡單:只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩下的參數。
簡單點來說就是:每次調用函數時,它只接受一部分參數,并返回一個函數,直到傳遞所有參數為止。
作用:參數復用、提前返回和?延遲執行
function add(a) {return function(b) {return a + b;};
}// 使用柯里化的函數
const add5 = add(5);
console.log(add5(3)); // 輸出 8延遲執行:柯里化可以將原本需要多個參數的函數轉換為一系列接受單個參數的函數,這樣就可以先傳入部分參數,延遲執行函數的調用。
參數復用:柯里化可以將一部分參數固定下來,形成一個新的函數,這樣就可以重復調用這個新函數并傳入不同的參數,而不用重復傳入固定的參數。
函數復用:柯里化可以幫助我們創建可以復用的函數,這樣可以減少代碼的重復編寫。
。
5.call,apply,bind
call 和 apply 的主要作用,是改變對象的執行上下文,并且是立即執行的。它們在參數上的寫法略有區別。
bind 也能改變對象的執行上下文,它與 call 和 apply 不同的是,返回值是一個函數,并且需要稍后再調用一下,才會執行。
function greet() {console.log(`Hello, ${this.name}!`);
}const person = { name: 'Alice' };
greet.call(person); // 輸出:Hello, Alice!
function greet() {console.log(`Hello, ${this.name}!`);
}const person = { name: 'Bob' };
const args = ['Alice']; // 函數調用時的參數列表
greet.apply(person, args); // 輸出:Hello, Alice!
function greet() {console.log(`Hello, ${this.name}!`);
}const person = { name: 'Charlie' };
const boundGreet = greet.bind(person);
boundGreet(); // 輸出:Hello, Charlie!
6.map()和parselnt()的區別
map()
?方法會返回一個新數組,其中的元素是對原始數組中的每個元素應用回調函數的結果。
// 將數組中的每個元素乘以 2
const numbers = [1, 2, 3, 4];
const doubled = numbers.map((num) => num * 2);
console.log(doubled); // 輸出: [2, 4, 6, 8]
parseInt()
?函數會返回解析后的整數。如果無法解析,則返回?NaN
(Not a Number)
parseInt('123', 5) // 將'123'看作 5 進制數,返回十進制數 38 => 1*5^2 + 2*5^1 + 3*5^0 = 38
7.事件冒泡和事件捕獲
事件冒泡(從里到外)
<div id="outer"><p id="inner">Click me!</p>
</div>當我們點擊P元素時,事件是這樣傳播的:p
div
body
html
document 現代瀏覽器都支持事件冒泡,IE9、Firefox、Chrome和Safari則將事件一直冒泡到window對象。
事件捕獲
當點擊P元素時,事件的傳播方向就變成了這樣:
- document
- html
- body
- div
- p
事件代理:利用事件冒泡機制,將事件處理程序綁定到一個父級元素上,從而管理其子元素上的事件。
<ul id="parent"><li>Item 1</li><li>Item 2</li><li>Item 3</li>
</ul>// 獲取父元素
const parent = document.getElementById('parent');// 父元素上綁定事件處理程序
parent.addEventListener('click', function(event) {// 判斷事件目標是否為子元素if (event.target.tagName === 'LI') {// 處理事件console.log('Clicked on item: ' + event.target.textContent);}
});
?8.var,let,const
- var: 函數作用域,會變量提升,可重復聲明,可重新賦值。
- let: 塊作用域,不會變量提升,不可重復聲明,可重新賦值。
- const: 塊作用域,不會變量提升,不可重復聲明,不可重新賦值。
9.?promise,async,await
一個Promise有三種可能的狀態:
- pending(待定)?:初始狀態,既不是成功,也不是失敗。
- fulfilled(已實現)?:意味著操作成功完成。
- rejected(已拒絕)?:意味著操作失敗。
展示鏈式調用和錯誤處理
new Promise((resolve, reject) => {setTimeout(() => resolve(1), 1000);
})
.then(result => {console.log(result); // 輸出 1return result * 2;
})
.then(result => {console.log(result); // 輸出 2return result * 3;
})
.then(result => {console.log(result); // 輸出 6return result * 4;
})
.catch(error => {console.log('捕獲到錯誤:', error);
});
?async
和await
是建立在Promise之上的高級抽象,使得異步代碼的編寫和閱讀更加接近于同步代碼的風格。
通過在函數聲明前加上async
關鍵字,可以將任何函數轉換為返回Promise的異步函數。這意味著你可以使用.then()
和.catch()
來處理它們的結果。
await
關鍵字只能在async
函數內部使用。它可以暫停async函數的執行,等待Promise的解決(resolve),然后以Promise的值繼續執行函數。
async function asyncFunction() {let promise = new Promise((resolve, reject) => {setTimeout(() => resolve("完成"), 1000)});let result = await promise; // 等待,直到promise解決 (resolve)console.log(result); // "完成"
}asyncFunction();
手寫promise代碼
class MyPromise {constructor(executor) {this.state = 'pending';this.value = undefined;this.reason = undefined;this.onResolvedCallbacks = [];this.onRejectedCallbacks = [];const resolve = (value) => {if (this.state === 'pending') {this.state = 'fulfilled';this.value = value;this.onResolvedCallbacks.forEach(callback => callback());}};const reject = (reason) => {if (this.state === 'pending') {this.state = 'rejected';this.reason = reason;this.onRejectedCallbacks.forEach(callback => callback());}};try {executor(resolve, reject);} catch (error) {reject(error);}}then(onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };const promise2 = new MyPromise((resolve, reject) => {if (this.state === 'fulfilled') {setTimeout(() => {try {const x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);}if (this.state === 'rejected') {setTimeout(() => {try {const x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);}if (this.state === 'pending') {this.onResolvedCallbacks.push(() => {setTimeout(() => {try {const x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);});this.onRejectedCallbacks.push(() => {setTimeout(() => {try {const x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);});}});return promise2;}catch(onRejected) {return this.then(null, onRejected);}
}function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise'));}let called = false;if (x !== null && (typeof x === 'object' || typeof x === 'function')) {try {const then = x.then;if (typeof then === 'function') {then.call(x, value => {if (called) return;called = true;resolvePromise(promise2, value, resolve, reject);}, reason => {if (called) return;called = true;reject(reason);});} else {resolve(x);}} catch (error) {if (called) return;called = true;reject(error);}} else {resolve(x);}
}
10.Ajax、Fetch、axios
?Ajax 是一個技術統稱,是一個概念模型,它囊括了很多技術,并不特指某一技術,它很重要的特性之一就是讓頁面實現局部刷新。
1)利用 XMLHttpRequest 模塊實現 Ajax。
<body><script>function ajax(url) {const xhr = new XMLHttpRequest();xhr.open("get", url, false);xhr.onreadystatechange = function () {// 異步回調函數if (xhr.readyState === 4) {if (xhr.status === 200) {console.info("響應結果", xhr.response)}}}xhr.send(null);}ajax('https://smallpig.site/api/category/getCategory')</script>
</body>
注意:?我們使用這種方式實現網絡請求時,如果請求內部又包含請求,以此循環,就會出現回調地獄,這也是一個詬病,后來才催生了更加優雅的請求方式。
2)Fetch 是在 ES6 出現的,它使用了 ES6 提出的 promise 對象。它是 XMLHttpRequest 的替代品。
Fetch 是一個 API,它是真實存在的,它是基于 promise 的。
<body><script>function ajaxFetch(url) {fetch(url).then(res => res.json()).then(data => {console.info(data)})}ajaxFetch('https://smallpig.site/api/category/getCategory')</script>
</body>
?3)Axios 是一個基于 promise 封裝的網絡請求庫,它是基于 XHR 進行二次封裝。
// 發送 POST 請求
axios({method: 'post',url: '/user/12345',data: {firstName: 'Fred',lastName: 'Flintstone'}
})
Ajax、Fetch、axios三者之間的關系可以用一張圖來清晰的表示,如圖:?
?
11.原型對象與原型鏈
原型對象(prototype):每個函數都有一個特殊的屬性叫做原型對象【prototype】
- js是基于原型的語言,每個對象都擁有一個原型對象,對象以其原型為模板、從原型繼承方法和屬性。這些屬性和方法時定義在對象的構造函數之上的prototype屬性上,而非對象的實例本身。
- 原型對象可以再擁有原型對象,并從中繼承方法和屬性,一層一層,層層向上直到一個對象的原型對象為 null,這種就是原型鏈。
- 創建對象實例時,對象的實例和它的構造器之間建立一個鏈接【__proto__屬性,是從構造函數的prototype屬性派生的。也就是__proto__與構造函數的prototype是指向同個對象】Object.getPrototypeof(new Foobar())和Foobar.prototype是相等的
-
查找屬性的過程: 1.先查找自己身屬性是否由包含該屬性。 2.如果沒有,才會沿著原型鏈,層層向上搜索,直到找到名字的屬性 3.如果找到最后原型鏈的末尾,即最后的原型為null,那就是沒有找到該屬性。就會返回undefined
-
JS中的對象都內置了__proto__屬性,但是只有函數對象內置了prototype屬性,
-
函數對象除了具有
__proto__
屬性外,還具有prototype
屬性。prototype
是函數對象獨有的屬性,它是在函數被創建時自動添加的,指向一個對象,該對象就是函數的原型。當函數作為構造函數被調用時,通過new
關鍵字創建的實例對象會繼承該函數的prototype
對象上的屬性和方法。
function Person(name) {this.name = name;
}Person.prototype.sayHello = function() {console.log('Hello, my name is ' + this.name);
};const person1 = new Person('Alice');person1 對象會繼承 Person.prototype 對象上的 sayHello 方法。
----------------------------------------------------分割線------------------------------------------------------
12. calc()
在編寫?calc()
?函數語法時,必須在每個操作之間包含空格,特別是在使用?+
?和?-
?操作符時,否則表達式將無效。
使用 calc() 實現動態的寬度或高度:
css
Copy code
.container {width: calc(100% - 20px);
}
將 calc() 與百分比和固定值一起使用:
css
Copy code
.sidebar {width: calc(25% - 10px);
}
在響應式布局中,結合 calc() 和視口單位:
css
Copy code
.header {height: calc(100vh - 50px);
}
將 calc() 用于調整字體大小:
css
Copy code
.text {font-size: calc(16px + 2vw);
}
13.動畫與過渡
-
CSS Transition
CSS 過渡,屬于補間動畫,即設置關鍵幀的初始狀態,然后在另一個關鍵幀改變這個狀態,比如大小、顏色、透明度等,瀏覽器將自動根據二者之間幀的值創建的動畫。 -
.element {transition: property duration timing-function delay; }
-
CSS Animation
CSS 動畫,可以理解是CSS Transition
的加強版,它既可以實現 補間動畫 的動畫效果,也可以使其以 逐幀動畫 的方式進行繪制。 -
@keyframes animation-name {from { /* 初始狀態 */ }to { /* 結束狀態 */ } }.element {animation: animation-name duration timing-function delay iteration-count direction fill-mode play-state; }
14.實現等高布局?
HTML 代碼:
html復制代碼<div class="container"><div class="left">left</div><div class="center">center</div><div class="right">right</div>
</div>CSS 代碼:
css復制代碼.left {background-color: red;
}
.center {background-color: green;
}
.right {background-color: blue;
}
1)padding + 負 margin
.container {overflow: hidden;
}
.center,
.left,
.right {padding-bottom: 10000px;margin-bottom: -10000px;
}
2)模仿 table 布局
.container {display: table;
}
.center,
.left,
.right {display: table-cell;
}
3)flex 實現
.container {display: flex;
}flex 元素默認占滿整個容器的高度,這樣各欄高度均為容器高度,實現等高。
實際上使用的是 align-items: stretch 屬性(默認)。
4)grid 實現
.container {display: grid;grid-auto-flow: column;
}
15.css實現三角形
.triangle {width: 0;height: 0;border-left: 50px solid transparent; /* 左邊框透明 */border-right: 50px solid transparent; /* 右邊框透明 */border-top: 50px solid red; /* 上邊框紅色 */
}
16.display,opocity,visiblity
display:none 與 visibility:hidden的區別visibility 擁有繼承性
visibility 不會影響 css 計數器
visibility 過渡效果有效,而 display 則無效
visibility 可以獲得元素的尺寸位置,而 display 則無法獲取
visibility 在無障礙訪問這一塊比 display 更友好
如果希望元素不可見,同時不占據空間,輔助設備無法訪問,但資源有加載,DOM 可 訪問,則可以直接使用 display:none 隱藏。
如果希望元素不可見,不能點擊,輔助設備無法訪問,但占據空間保留,則可以使用 visibility:hidden 隱藏。
如果希望元素不可見,但可以點擊,而且不占據空間,則可以使用透明度opacity: 0;。
16.?多行文本的省略顯示
1)使用-webkit-line-clamp
div {display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;-webkit-line-clamp: 2;
}除了-webkit-line-clamp其他屬性固定不變,主要是將對象作為彈性伸縮盒子模型顯示,并設置伸縮盒對象的子元素的排列方式。而-webkit-line-clamp是用來控制多少行進行省略
2)絕對定位
.wrap {position: relative;/*line-height和height要相互配合,顯示多少行就省略,就是line-height多少倍數*/line-height: 1.2em;max-height: 3.6em;/*此屬性看需求來判斷是否設置,因為設置了padding-right,多騰出了點位置,該值一般為padding-right的值的負值*//*margin-left: -1em;*//*此值寫死成1em就好,因為省略號大概就是占用1em的空間*/padding-right: 1em;text-align: justify;overflow: hidden;
}.wrap:before {position: absolute;right: 0;bottom: 0;content: '...';
}.wrap:after {position: absolute;right: 0;/*寬高寫死1em就好,因為省略號大概就是占用1em的空間,用來遮擋住省略號,也基本上跟wrap的padding-right一致*/width: 1em;/*與wrap的行高實際值保持一致*/height: 1.2em;content: '';/*要跟所在背景顏色一致才能遮擋住省略號后覺得沒異樣*/background-color: #fff;
}
3)float布局
.wrap {/*需要定高*/height: 100px;/*用來設置顯示多少行才省略,值一般為wrap的height值/行數求得,但是這個行數會受到字體大小的限制*//*字體太大了,設置顯示很多行也會很丑,都擠一塊了,所以這個實際值,要看具體需求和實踐*/line-height: 25px;/*加上此屬性顯示效果更佳,就算部分瀏覽器不支持也影響不大*/text-align: justify;overflow: hidden;
}.wrap:before {float: left;/*這個值可以隨意設定,不論單位還是什么*/width: 1em;height: 100%;content: '';
}.wrap:after {float: right;/*大小隨意,設置em單位最好,可隨字體大小變化而自適應*//*如果要采用以下漸變效果,那么這個值要大于before里的width值效果會比較好點*//*值越大,漸變的效果越明顯影響的范圍越大。*/width: 2.5em;/*與父元素wrap的行高實際px值一樣*/height: 25px;/*此值要跟自身寬度一樣,取負值*/margin-left: -2.5em;/*此值要跟before寬度一樣*/padding-right: 1em;content: '...';text-align: right;/*這里開始利用在float布局的基礎上進行定位移動了*/position: relative;/*與父元素wrap的行高實際值一樣,取負值*/top: -25px;left: 100%;/*設置漸變效果是為了省略號和內容銜接得自然點,沒那么突兀,要注意要跟文字所在的背景的顏色搭配(把white替換成背景色)*/background: #fff;background: -webkit-gradient(linear, left top, right top, from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
}.wrap .text {float: right;/*該值要等于wrap:before的width值*/margin-left: -1em;width: 100%;
}
4)
.ellipsis {overflow: hidden;text-overflow: ellipsis;white-space: nowrap;/* 如果需要多行省略,請取消注釋下面兩行 *//* display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2; */ /* 限制顯示的行數 */
}
17.BFC
BFC容器"通常是指"塊級格式化上下文容器"(Block Formatting Context Container)。塊級格式化上下文(BFC)是在CSS中用來管理和控制元素在頁面上布局和排列的一種機制。BFC容器是一種具有特定規則的HTML元素或CSS屬性,它們會創建一個獨立的上下文,影響其內部元素的布局和排列方式。BFC容器是CSS布局中的一個重要概念,可以幫助開發人員更精確地控制元素的布局和排列BFC容器"通常是指"塊級格式化上下文容器"(Block Formatting Context Container)。塊級格式化上下文(BFC)是在CSS中用來管理和控制元素在頁面上布局和排列的一種機制。BFC容器是一種具有特定規則的HTML元素或CSS屬性,它們會創建一個獨立的上下文,影響其內部元素的布局和排列方式。BFC容器是CSS布局中的一個重要概念,可以幫助開發人員更精確地控制元素的布局和排列哪些屬性可以創建BFC容器float: left || right
position: absolute || fixed
display: inline-block;
display: table-cell ....
overflow: hidden || auto || overly || scroll
彈性盒子 (display: flex || inline-flex)
18.實現垂直居中
1)僅居中元素定寬高適用
- absolute + 負margin
- absolute + margin auto
- absolute + calc
2)居中元素不定寬高
- absolute + transform
- lineheight
- writing-mode
- table
- css-table
- flex
- grid
<div class="wp"><div class="box size">123123</div>
</div>/* 公共代碼 */
.wp {border: 1px solid red;width: 300px;height: 300px;
}.box {background: green;
}.box.size{width: 100px;height: 100px;
}
/* 公共代碼 */
?CSS實現水平垂直居中的10種方式 - 掘金
19.偽類和偽元素
1)偽類
偽類是添加到選擇器的關鍵字,用于指定所選元素的特殊狀態。例如,偽類?:hover
?可以用于選擇一個按鈕,當用戶的指針懸停在按鈕上時,設置此按鈕的樣式。
前端常用的偽類有?:hover
、:focus
、:first-child
、:first-of-type
、:last-child
、:last-of-type
、:nth-child()
、:not()
、:has()
?等等。
2)偽元素
偽元素
是一個附加至選擇器末的關鍵詞,允許你對被選擇元素的特定部分修改樣式,例如 ::first-line
偽元素可以改變段落首行文字的樣式。一個選擇器只能使用一個相同類型的偽元素。
偽元素由冒號(::
)后跟著偽元素名稱組成,例如 ::before
、::after
等。
還在傻傻分不清常用偽類和偽元素?快來一文速覽! - 掘金
20.超寬文本設置為省略號
.text-ellipsis {white-space: nowrap; /* 不換行 */overflow: hidden; /* 溢出隱藏 */text-overflow: ellipsis; /* 使用省略號 */
}