typescript型別
工具Readonly
interface A {
a: string;
b: number;
c: number[];
}
type C = Readonly<A>
const c: C = {a: '', b: 18, c: [1, 2]}
c.a = "1" // 報紅
工具Partial
interface A {
a: string;
b: number;
c: number[];
}
type B = Partial<A>
const a: A = {a: '', b: 18, c: [1, 2]};
const b: B = {a: ''};
工具Pick/Omit
interface A {
a: string;
b: number;
c: number[];
}
type B = Pick<A, 'a' | 'b'>;
type C = Omit<A, 'a'>;
const b: B = {a: "", b: 0};
const c: C = {b: 1, c: [0]};
工具Record
type A = Record<'a' | 'b' | 'c', string>
const c: A = {a: "a", b: "b", c: "c"};
class類的屬性名
class A {
a: number = 1;
b: string = "";
}
type AFields = keyof InstanceType<typeof A>; // "a" | "b"
反轉
type A = {
a: "x";
b: "y";
}
type Reverse<T extends Record<keyof T, keyof any>> = {
[P in T[keyof T]]: {
[K in keyof T]: T[K] extends P ? K : never
}[keyof T]
}
type B = Reverse<A>;
const b: B = {x: "a", y: "b"};
傳入不同的值返回的結果型別不同
interface A {
a: string;
}
interface B {
b: string;
}
interface C {
c: string;
}
interface Types {
a: A;
b: B;
c: C;
}
function fun<T extends keyof Types> (type: T): Types[T] {
return ;
}
功能
全屏
// 進入全屏
function enter(ele) {
if (ele.requestFullScreen) {
ele.requestFullScreen();
} else if (ele.mozRequestFullScreen) {
ele.mozRequestFullScreen();
} else if (ele.webkitRequestFullScreen) {
ele.webkitRequestFullScreen();
} else if (ele.msRequestFullScreen) {
ele.msRequestFullScreen();
}
}
// 退出全屏
function exit() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
// 是否全屏
function isFullscreen() {
return Boolean(
document.fullscreenElement ||
document.mozFullscreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement ||
null
);
}
下載
<a href="https://wx3.sinaimg.cn/mw2000/eb7b830aly1hmarcfijnhj20kg0kgadg.jpg">下載</a>
<a href="https://wx3.sinaimg.cn/mw2000/eb7b830aly1hmarcfijnhj20kg0kgadg.jpg" xld="true">迅雷下載</a>
<script>
const links = document.querySelectorAll("a[xld]");
links.forEach((link) => {
link.href = `thunder://${btoa(`AA${link.href}ZZ`)}`;
});
</script>
<a href="thunder://QUFodHRwczovL3d4My5zaW5haW1nLmNuL213MjAwMC9lYjdiODMwYWx5MWhtYXJjZmlqbmhqMjBrZzBrZ2FkZy5qcGdaWg==" xld="true">迅雷下載</a>
解決文字框中文輸入導致高頻觸發
let composition = false;
input.addEventListener("input", function () {
if (!composition) {
search();
}
});
// 開始輸入中文拼音了
input.addEventListener("compositionstart", function () {
composition = true;
});
// 結束輸入中文拼音了
input.addEventListener("compositionend", function () {
composition = false;
search();
});
公共函式
型別判斷
function determineType(target) {
const type = typeof target;
switch (type) {
case "bigint":
case "boolean":
case "function":
case "number":
case "string":
case "symbol":
case "undefined":
return type;
case "object":
if (target instanceof Array) {
return 'array';
}
if (target instanceof Object) {
return 'object';
}
return 'null';
default:
return "undefined";
}
}
陣列分組
function groupBy (arr, generateKey) {
if (typeof generateKey === "string") {
const propName = generateKey;
generateKey = (item) => item[propName];
}
const result = {};
for (let i = 0; i < arr.length; i++) {
const key = generateKey(arr[i], i, arr);
if (result[key]) {
result[key].push(arr[i]);
} else {
result[key] = [arr[i]];
}
}
return result;
}
複製
export function copyText (value) {
const oInput = document.createElement('input');
oInput.value = value;
document.body.appendChild(oInput);
oInput.select();
document.execCommand('Copy');
oInput.className = 'oInput';
oInput.style.display = 'none';
}
請求重試
function request (url, maxCount) {
return fetch(url).catch(err => maxCount <= 0 ? Promise.reject(err) : request(url, maxCount - 1));
}
併發請求
// 請求陣列,最大併發
function concurRequest (requestList, max) {
if (!requestList.length) {
return Promise.resolve([]);
}
return new Promise((resolve) => {
let index = 0;
let count = 0;
let result = [];
async function _request () {
const i = index;
const request = requestList[index];
index++;
try {
result[i] = await request();
} catch (e) {
result[i] = e;
} finally {
count++;
if (count === requestList.length) {
resolve(result);
}
if (index < requestList.length) {
_request();
}
}
}
for (let i = 0; i < Math.min(requestList.length, max); i++) {
_request();
}
});
}
class轉function
"use strict";
class B {
constructor (name) {
this.name = name;
}
logName () {
console.log(this.name);
}
}
function A (name) {
if (!new.target) {
throw new TypeError("是類不是函式");
}
this.name = name;
}
Object.defineProperty(A.prototype, 'logName', {
value: function () {
if (new.target) {
throw new TypeError("是函式不是類");
}
console.log(this.name);
},
enumerable: false, // 是否可被遍歷
// writable: false, // 是否可寫
// configurable: false // 屬性描述符本身能否被再次修改
});
訪問器
function A (x, y) {
this.x = x;
this.y = y;
}
Object.defineProperty(A.prototype, "add", {
get: function () {
return this.x + this.y;
}
});
const a = new A(1, 2);
console.log(a.add); // 3
a.x++
console.log(a.add); // 4
修改必包內的私有變數
const o = (function () {
const a = {
x: 1,
y: 2
};
// Object.setPrototypeOf(a, null); // 防禦
return {
get: function (key) {
// 防禦:
// if(Object.hasOwnProperty(key)){
// return a[key];
// }
return a[key];
}
};
}());
// 攻擊:不改變上面程式碼,修改必包內a物件的屬性值
Object.defineProperty(Object.prototype, "hack", {
get() {
return this;
}
});
const a = o.get("hack");
a["z"] = 3;
console.log(o.get("z"));
CSS
立體陰影
<h1>立體陰影</h1>
<style>
h1 {
font-weight: 800;
position: relative;
color: #FFFFFF;
font-size: 120px;
}
h1::after {
content: "立體陰影";
position: absolute;
left: 0;
color: #000000;
transform: translate(-69px, 24px) scaleY(0.5) skew(50deg);
z-index: -1;
filter: blur(2px);
-webkit-mask: linear-gradient(transparent, #000000);
}
</style>
玻璃磨砂和黑白
.glass {
background: rgba(255, 255, 255, 0.4);
/*背後的東西模糊*/
backdrop-filter: blur(3px);
/*背後的東西變黑白*/
/*backdrop-filter: grayscale(1);*/
}
彈幕避開人像
.mask {
mask-image: url("./image.svg");
mask-size: cover;
}
條紋狀
.colorBorder {
background: repeating-linear-gradient(-45deg, #0b5eef 0px 10px, #fff 10px 20px, #f60707 20px 30px, #fff 30px 40px);
}
聚焦子元素父元素樣式發生變化
<div class="container">
<input class="input">
</div>
<style>
<!-- focus-within表示當前元素以及後代元素有沒有聚焦 -->
.container:focus-within {
background-color: #999999;
}
.input:focus {
border: 1px solid #18AEFF;
}
</style>
必選
<label class="label">
<span class="title">Name</span>
<input class="input" data-required>
</label>
<style>
.label .title:has(+ .input[data-required])::after {
content: "*";
color: #f62323;
display: inline-block;
}
</style>
首字母
.content::first-letter {
}
文字選擇
.content::selection {
}
動態規劃
揹包放入的最大價值
const maxWeight = 6;
// [v價值, w重量]
const goodsList = [{v: 5, w: 2}, {v: 10, w: 5}, {v: 3, w: 1}, {v: 6, w: 4}, {v: 3, w: 3}];
// 求放入揹包的最大價值
function maxPackageWorth (maxWeight, goodsList) {
let line = [];
for (let i = 0; i <= maxWeight; i++) {
const goods = goodsList[0];
line[i] = i >= goods.w ? goods.v : 0;
}
for (let i = 1; i < goodsList.length; i++) {
const next = [];
const goods = goodsList[i];
for (let j = 0; j <= maxWeight; j++) {
if (j < goods.w) {
next[j] = line[j];
} else {
next[j] = Math.max(
goods.v + line[j - goods.w],
line[j]
);
}
}
line = next;
}
return line[maxWeight];
}
maxPackageWorth(maxWeight, goodsList);
模型
洋蔥任務模型
// 洋蔥模型
class TaskPro {
// 任務列表
_taskList = [];
// 正在執行
_isRunning = false;
// 正在執行的任務下標
_currentIndex = 0;
// 取出一個任務執行
async _runTask() {
// 任務執行完畢
if (this._currentIndex >= this._taskList.length) {
this._isRunning = false;
this._currentIndex = 0;
this._taskList = [];
return;
}
const b = this._currentIndex;
const task = this._taskList[this._currentIndex];
await task(this._next.bind(this));
const a = this._currentIndex;
// 判讀task內有沒有手動執行next
if (b === a) {
await this._next();
}
}
// 執行下一個任務
async _next() {
this._currentIndex++;
await this._runTask();
}
// 新增任務
addTask(task) {
if (typeof task === "function") {
this._taskList.push(task);
}
}
// 開始執行任務
async run() {
if (this._isRunning) {
return;
}
this._isRunning = true;
await this._runTask();
}
}
const taskPro = new TaskPro();
taskPro.addTask(async (next) => {
console.log(1);
await next();
});
taskPro.addTask(() => {
console.log(2);
});
taskPro.run();
Proxy累加
function createAddProxy(value = 0) {
return new Proxy({}, {
get(target, key) {
if (key === Symbol.toPrimitive) {
return () => value;
}
return createAddProxy(value + Number(key));
}
});
}
const add = createAddProxy();
console.log(add[1][3][1000] + 1); // 1005