<button onclick="onUnlockScreen()">釋放</button>

<div id="statusElem"></div>
<script>
let wakeLock = null;
async function onLockScreen() {
// create an async function to request a wake lock
try {
wakeLock = await navigator.wakeLock.request("screen");
statusElem.textContent = "喚醒鎖已激活";

wakeLock.addEventListener("release", () => {
// the wake lock has been released
statusElem.textContent = "喚醒鎖已釋放";
});
} catch (err) {
// The Wake Lock request has failed - usually system related, such as battery.
statusElem.textContent = ${err.name}, ${err.message}; } } async function onUnlockScreen() { if (!wakeLock) return; wakeLock.release().then(() => { wakeLock = null; }); } </script>

截圖_20242212092253.png

Cookie Store API[20]

按照以往,開發者如何獲得cookie信息呢,當然是?document.cookie,

截圖_20240310232535.png

這種的缺點是沒法知道 domainpathexpired等信息。

當然,開發者借用開發者工具,可以獲取更加詳細的信息:

截圖_20240310232700.png

Cookie Store API[21]?可以獲得開發工具一樣的cookie屬性,當然 具有?HttpOnly的屬性的是獲取不到的。

截圖_20240310232916.png

當然還提供了

Compression Stream API[25]

Compression Stream API?提供了一種 JavaScript API,使用 gzip 或者默認格式壓縮和解壓縮數據流。內置的壓縮庫意味著 JavaScript 應用不再需要包含其它壓縮庫,這使得應用程序的下載大小更小。

比如下面的就是上傳一個文本文件到瀏覽器,代碼采用gzip壓縮純文本后,從6kb變為了1kb,解壓縮后又變成了6kb。

截圖_20242612102650.png

代碼嘛,簡簡單單。

<input type="file" id="file" >
<script>
async function compressAndDownload(filename, content) {
// 創建原始數據流
const stringStream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode(content));
controller.close();
}
});

// 創建壓縮流
const compressionStream = new CompressionStream('gzip');

// 將原始數據流連接到壓縮流
const compressedStream = stringStream.pipeThrough(compressionStream);

// 創建ArrayBuffer容器接收壓縮數據
const chunks = [];
const reader = compressedStream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
} finally {
reader.releaseLock();
}

// 合并壓縮數據并創建Blob
const compressedBlob = new Blob(chunks, { type: 'application/gzip' });

// 創建下載鏈接
const url = URL.createObjectURL(compressedBlob);
const link = document.createElement('a');
link.href = url;
link.download = ${filename}.gz; document.body.appendChild(link); // 觸發下載 link.click(); // 清理 setTimeout(() => { document.body.removeChild(link); URL.revokeObjectURL(url); }, 0); } file.addEventListener('change', async (event) => { if(event.target.files.length === 0){ return; } const file = event.target.files[0]; const reader = new FileReader(); reader.readAsText(event.target.files[0]); reader.onload = async () => { const content = reader.result; compressAndDownload(file.name, content); } }) </script>

CSS Custom Highlight API[26]

CSS 自定義高亮 API 提供了一種方法,可以通過使用 JavaScript 創建范圍并使用 CSS 定義樣式來設置文檔中任意文本范圍的樣式。

感興趣的同學,可以去 MDN 在線的示例 進行實操?CSS Custom Highlight API#Result[27]

截圖_20243812103845.png

其邏輯是就是查找所有文本節點,收集匹配內容的Range, 最后作為參數構建 HighLight對象, 需要注意的是其 并未產生新的節點

核心邏輯代碼如下:

const query = document.getElementById("query");
const article = document.querySelector("article");

// Find all text nodes in the article. We'll search within these text nodes.
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
allTextNodes.push(currentNode);
currentNode = treeWalker.nextNode();
}
// Listen to the input event to run the search.
query.addEventListener("input", () => {
// If the CSS Custom Highlight API is not supported, display a message and bail-out.
if (!CSS.highlights) {
article.textContent = "CSS Custom Highlight API not supported.";
return;
}

// Clear the HighlightRegistry to remove the previous search results.
CSS.highlights.clear();

// Clean-up the search query and bail-out if if it's empty.
const str = query.value.trim().toLowerCase();
if (!str) {
return;
}

// Iterate over all text nodes and find matches.
const ranges = allTextNodes
.map((el) => {
return { el, text: el.textContent.toLowerCase() };
})
.map(({ text, el }) => {
const indices = [];
let startPos = 0;
while (startPos < text.length) {
const index = text.indexOf(str, startPos);
if (index === -1) break;
indices.push(index);
startPos = index + str.length;
}

// Create a range object for each instance of str we found in the text node.
return indices.map((index) => {
const range = new Range();
range.setStart(el, index);
range.setEnd(el, index + str.length);
return range;
});
});

// Create a Highlight object for the ranges.
const searchResultsHighlight = new Highlight(...ranges.flat());

// Register the Highlight object in the registry.
CSS.highlights.set("search-results", searchResultsHighlight);
});

EyeDropper[28]

可以打開并使用它從屏幕上選擇顏色。

記住了,是從屏幕上拾取顏色, 下面的截圖就是從瀏覽器外的背景桌面拾取了衣服的顏色, 真不錯。

基于這個做個取色插件,是不是分分鐘就搞定呢?

截圖_20242312032354.png

代碼,簡簡單單二三十行:

 <button id="start-button">打開拾色器</button>
<img src="https://img.alicdn.com/imgextra/i1/O1CN01CC9kic1ig1r4sAY5d_!!6000000004441-2-tps-880-210.png" />
<div>
顏色是:<span id="result"></span>
</div>
<script>
document.getElementById("start-button").addEventListener("click", () => {
const resultElement = document.getElementById("result");

if (!window.EyeDropper) {
resultElement.textContent = "你的瀏覽器不支持 EyeDropper API";
return;
}

const eyeDropper = new EyeDropper();
const abortController = new AbortController();

eyeDropper
.open({ signal: abortController.signal })
.then((result) => {
resultElement.textContent = result.sRGBHex;
resultElement.style.backgroundColor = result.sRGBHex;
})
.catch((e) => {
resultElement.textContent = e;
});
});

</script>

Prioritized Task Scheduling API[29]

提供了一種標準化的方法,用于對屬于應用程序的所有任務進行優先級排序。

優先級任務調度API允許開發者為異步任務分配優先級,這些任務按照以下三種優先級順序執行:

  1. user-blocking這類任務優先級最高,它們直接影響用戶的交互體驗。這類任務主要包括頁面渲染至可交互狀態的過程,以及對用戶輸入的即時響應。例如,頁面初次加載的核心內容渲染、按鈕點擊事件的處理等。
  2. user-visible:這類任務雖可見于用戶界面,但并不阻止用戶繼續進行其他操作。這類任務包括渲染頁面的非關鍵部分,例如非核心圖片加載、非關鍵動畫渲染等。這是默認的優先級等級。
  3. background優先級最低的一類任務,它們對時間要求不嚴苛,可以在不影響用戶體驗的前提下稍后執行。這類任務包括日志處理、非必需的第三方庫初始化以及其他不影響頁面即時呈現的工作。這些任務通常在主線程空閑時執行,以避免阻塞用戶可見或交互相關的高優先級任務。

欸,這就給高端玩家無限遐想了,只能一個字表達  太牛了

下面一個例子,來看看優先級的輸出情況, 可以看到,如你所愿:

    <div id="log"></div>
<script>
let log = document.getElementById("log");
function mylog(text) {
log.innerHTML += ${text}<br/>; } // three tasks, in reverse order of priority scheduler.postTask(() => mylog("background 1"), { priority: "background" }); scheduler.postTask(() => mylog("user-visible 1"), { priority: "user-visible" }); scheduler.postTask(() => mylog("user-blocking 1"), { priority: "user-blocking" }); // three more tasks, in reverse order of priority scheduler.postTask(() => mylog("background 2"), { priority: "background" }); scheduler.postTask(() => mylog("user-visible 2"), { priority: "user-visible" }); scheduler.postTask(() => mylog("user-blocking 2"), { priority: "user-blocking" }); // Task with default priority: user-visible scheduler.postTask(() => mylog("user-visible 3 (default)")); </script>

截圖_20240012040015.png

Trusted Types API[30]

Web開發者提供了一種鎖定DOM API中不安全部分的方法,目的是防止客戶端跨站腳本(Cross-site scripting,XSS)攻擊

在下面的例子中,通過TrustedTypePolicyFactory.createPolicy()方法創建一個策略,通過TrustedTypePolicy.createHTML方法創建一個安全的HTML字符串插入到文檔中。

有很大的靈活性,策略是自己可以定義的。

<div id="myDiv"></div>

<script>

var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": ''',
"/": '/'
};
// 創建一個策略,該策略將用于將不受信任的輸入轉換為安全的內容。
const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
createHTML: (string) => string.replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
}),
});

let el = document.getElementById("myDiv");
const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
console.log(escaped instanceof TrustedHTML); // true
el.innerHTML = escaped;

</script>

除此之外,還可以用來創建用來檢查?Script?和?ScriptURL的策略。

const policy = trustedTypes.createPolicy("myPolicy", {
createScriptURL: (s, type, sink) => { //......},
createScript: (s) => { //......}
});

CSS Font Loading API[31]

CSS 字體加載 API 為你提供了動態加載字體資源的事件和接口。

以往引入字體主要是靠 css 來實現的, 動態引入字體也可以通過動態添加link節點來實現。

@font-face {
2 font-family: 'MyCustomFont';
3 src: url('fonts/mycustomfont.woff2') format('woff2'),
4 url('fonts/mycustomfont.woff') format('woff');
5 font-weight: normal;
6 font-style: normal;
7}

現在呢, 內置了原生AP, 能動態加載字體,而且能控制加載時機,以及加載的狀態。

const font = new FontFace("myfont", "url(myfont.woff)", {
style: "italic",
weight: "400",
stretch: "condensed",
});

// 加載字體
font.load().then(()=>{
// 加載完畢
}, (err) => {
// 加載異常
console.error(err);
},);

// 等待到所有的字體都加載完畢
document.fonts.ready.then(() => {
// 使用該字體渲染文字(如:在 canvas 中繪制)
});

Popover API[32]

Popover API為開發者提供了一個標準、一致且靈活的機制,用于在頁面其他內容之上展示彈出內容。這種彈出內容可以通過HTML屬性聲明性控制,也可以通過JavaScript編程方式進行控制。

下面的例子就是?0?行javascript實現的彈框。

圖片
截圖_20245312015341.png

可以在 Using the Popover API#Result[33] 查看源碼和體驗, 還可以在 MDN Popover API examples[34] 看到更多的示例

URL Pattern API[35]

URL Pattern API 定義了一種語法,該語法用于創建URL模式匹配器。這些模式能夠與完整的URL或URL的各個組成部分進行匹配。其借鑒了?path-to-regexp[36]的語法。

path-to-regexp[37] 這個庫你也許不知道嗎,但是你一定用過, express , koa-touer 等等底層路由都是依賴這個庫。

匹配模塊包含:URL Pattern API 的模式語法包括:

  1. 字面字符串:將精確匹配的文本字符串,例如 “/home” 或 “/contact”。
  2. 通配符:如 “/posts/ ” 中的星號 ( ) 表示匹配任何字符序列,直至遇到下一個路徑分隔符(/)。
  3. 命名組:如 “/books/:id” 中的 “:id”,它會提取匹配URL中對應部分的值,作為單獨的數據項。
  4. 非捕獲組:如 “/books{/old}?”,這里的花括號 {...}? 表示該部分模式是可選的,可以匹配0次或1次,且不會作為一個單獨的數據項提取出來。
  5. 正則表達式組:如 “/books/(\d+)” 中的?(\d+),這部分遵循JavaScript正則表達式的規則,用于進行復雜匹配,盡管在URL Pattern API中有一定的限制。例如,此處的正則表達式將匹配一個或多個數字字符,并將其作為一個獨立的數據項提取出來。
// A pattern matching with a named group
const pattern = new URLPattern({ pathname: "/books/:id" });
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.exec("https://example.com/books/123").pathname.groups); // { id: '123' }

Audio Output Devices API[38]

音頻輸出設備API(Audio Output Devices API)賦予了Web應用程序能力,使其能夠詢問用戶希望使用哪個音頻輸出設備進行聲音播放。

欸, 可以選擇音頻輸出設備,還是比較有意思的。協議原文?Audio Output Devices API[39], 可惜還沒有瀏覽器支持。

document.querySelector("#myButton").addEventListener("click", async () => {
if (!navigator.mediaDevices.selectAudioOutput) {
console.log("selectAudioOutput() not supported or not in secure context.");
return;
}

// Display prompt to select device
const audioDevice = await navigator.mediaDevices.selectAudioOutput();

// Create an audio element and start playing audio on the default device
const audio = document.createElement("audio");
audio.src = "https://example.com/audio.mp3";
audio.play();

// Change the sink to the selected audio output device.
audio.setSinkId(audioDevice.deviceId);
});

Device Memory API[40]

傳統上,開發人員評估客戶端設備性能時,由于無法直接獲取設備的RAM大小信息,他們往往需要采取一些經驗法則,或是通過設備基準測試,抑或是根據設備制造商、用戶代理(User Agent)字符串等其他因素間接推測設備能力。

但現在,有以下兩種方法可以直接或間接確定設備的大致RAM量:

  1. Device Memory JavaScript API:這個API為開發者提供了一種直接了解設備內存(RAM)容量的方式。通過navigator.deviceMemory屬性,可以獲得設備內存級別的大致信息,如0.5表示小于1GB的RAM,1表示1-2GB,以此類推。
  2. 接受Client Hints:客戶端提示(Client Hints)是一種HTTP協議擴展,允許瀏覽器在HTTP請求中主動發送設備能力相關信息。其中,Device-Memory HTTP請求頭就包含了設備的內存類別信息。雖然這不是直接在JavaScript中獲取,但服務器可以根據這個頭信息動態調整響應內容,幫助開發者根據設備RAM大小優化用戶體驗。
const RAM = navigator.deviceMemory;  // 8

值是 0.250.51248之一,所以機器 16G內存,顯示的也是8。

Barcode Detection API[41]

用于檢測圖像中的條形碼和二維碼。

欸, 這就很有意思,配和?navigator.mediaDevices.getUserMedia喚起攝像頭,定期截圖分析,是不是就是一個web版本的掃碼能力呢?

截圖_20245712025755.png

if (!("BarcodeDetector" in globalThis)) {
console.log("此瀏覽器不支持條形碼檢測器。");
} else {
console.log("條形碼檢測器是支持的!");

// 創建新檢測器
const barcodeDetector = new BarcodeDetector({
formats: ["code_39", "codabar", "ean_13"],
});

barcodeDetector
.detect(imageEl)
.then((barcodes) => {
barcodes.forEach((barcode) => console.log(barcode.rawValue));
})
.catch((err) => {
console.log(err);
});

}

CSS Typed Object Model API[42]

CSS Typed Object Model(CSSOM)API從根本上改變了開發者在JavaScript中處理CSS屬性的方式,通過引入類型安全性和效率優化。

比如:簡簡單單就能獲取樣式的鍵值對, 其實還有一個結果有類似功能API?window.getComputedStyle

本文章轉載微信公眾號@成長的程序世界

上一篇:

LLM Agent之結構化輸出

下一篇:

Requests:API調用界的優雅紳士,告別復雜的HTTP請求!
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費