<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]

按照以往,開發(fā)者如何獲得cookie信息呢,當(dāng)然是?document.cookie,

截圖_20240310232535.png

這種的缺點(diǎn)是沒法知道 domainpathexpired等信息。

當(dāng)然,開發(fā)者借用開發(fā)者工具,可以獲取更加詳細(xì)的信息:

截圖_20240310232700.png

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

截圖_20240310232916.png

當(dāng)然還提供了

Compression Stream API[25]

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

比如下面的就是上傳一個(gè)文本文件到瀏覽器,代碼采用gzip壓縮純文本后,從6kb變?yōu)榱?kb,解壓縮后又變成了6kb。

截圖_20242612102650.png

代碼嘛,簡(jiǎn)簡(jiǎn)單單。

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

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

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

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

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

// 創(chuàng)建下載鏈接
const url = URL.createObjectURL(compressedBlob);
const link = document.createElement('a');
link.href = url;
link.download = ${filename}.gz; document.body.appendChild(link); // 觸發(fā)下載 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 創(chuàng)建范圍并使用 CSS 定義樣式來(lái)設(shè)置文檔中任意文本范圍的樣式。

感興趣的同學(xué),可以去 MDN 在線的示例 進(jìn)行實(shí)操?CSS Custom Highlight API#Result[27]

截圖_20243812103845.png

其邏輯是就是查找所有文本節(jié)點(diǎn),收集匹配內(nèi)容的Range, 最后作為參數(shù)構(gòu)建 HighLight對(duì)象, 需要注意的是其 并未產(chǎn)生新的節(jié)點(diǎn)。

核心邏輯代碼如下:

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]

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

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

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

截圖_20242312032354.png

代碼,簡(jiǎn)簡(jiǎn)單單二三十行:

 <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]

提供了一種標(biāo)準(zhǔn)化的方法,用于對(duì)屬于應(yīng)用程序的所有任務(wù)進(jìn)行優(yōu)先級(jí)排序。

優(yōu)先級(jí)任務(wù)調(diào)度API允許開發(fā)者為異步任務(wù)分配優(yōu)先級(jí),這些任務(wù)按照以下三種優(yōu)先級(jí)順序執(zhí)行:

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

欸,這就給高端玩家無(wú)限遐想了,只能一個(gè)字表達(dá)  太牛了。

下面一個(gè)例子,來(lái)看看優(yōu)先級(jí)的輸出情況, 可以看到,如你所愿:

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

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

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

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

<script>

var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": ''',
"/": '/'
};
// 創(chuàng)建一個(gè)策略,該策略將用于將不受信任的輸入轉(zhuǎn)換為安全的內(nèi)容。
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>

除此之外,還可以用來(lái)創(chuàng)建用來(lái)檢查?Script?和?ScriptURL的策略。

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

CSS Font Loading API[31]

CSS 字體加載 API 為你提供了動(dòng)態(tài)加載字體資源的事件和接口。

以往引入字體主要是靠 css 來(lái)實(shí)現(xiàn)的, 動(dòng)態(tài)引入字體也可以通過動(dòng)態(tài)添加link節(jié)點(diǎn)來(lái)實(shí)現(xiàn)。

@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}

現(xiàn)在呢, 內(nèi)置了原生AP, 能動(dòng)態(tài)加載字體,而且能控制加載時(shí)機(jī),以及加載的狀態(tài)。

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為開發(fā)者提供了一個(gè)標(biāo)準(zhǔn)、一致且靈活的機(jī)制,用于在頁(yè)面其他內(nèi)容之上展示彈出內(nèi)容。這種彈出內(nèi)容可以通過HTML屬性聲明性控制,也可以通過JavaScript編程方式進(jìn)行控制。

下面的例子就是?0?行javascript實(shí)現(xiàn)的彈框。

圖片
截圖_20245312015341.png

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

URL Pattern API[35]

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

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

匹配模塊包含:URL Pattern API 的模式語(yǔ)法包括:

  1. 字面字符串:將精確匹配的文本字符串,例如 “/home” 或 “/contact”。
  2. 通配符:如 “/posts/ ” 中的星號(hào) ( ) 表示匹配任何字符序列,直至遇到下一個(gè)路徑分隔符(/)。
  3. 命名組:如 “/books/:id” 中的 “:id”,它會(huì)提取匹配URL中對(duì)應(yīng)部分的值,作為單獨(dú)的數(shù)據(jù)項(xiàng)。
  4. 非捕獲組:如 “/books{/old}?”,這里的花括號(hào) {...}? 表示該部分模式是可選的,可以匹配0次或1次,且不會(huì)作為一個(gè)單獨(dú)的數(shù)據(jù)項(xiàng)提取出來(lái)。
  5. 正則表達(dá)式組:如 “/books/(\d+)” 中的?(\d+),這部分遵循JavaScript正則表達(dá)式的規(guī)則,用于進(jìn)行復(fù)雜匹配,盡管在URL Pattern API中有一定的限制。例如,此處的正則表達(dá)式將匹配一個(gè)或多個(gè)數(shù)字字符,并將其作為一個(gè)獨(dú)立的數(shù)據(jù)項(xiàng)提取出來(lái)。
// 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]

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

欸, 可以選擇音頻輸出設(shè)備,還是比較有意思的。協(xié)議原文?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]

傳統(tǒng)上,開發(fā)人員評(píng)估客戶端設(shè)備性能時(shí),由于無(wú)法直接獲取設(shè)備的RAM大小信息,他們往往需要采取一些經(jīng)驗(yàn)法則,或是通過設(shè)備基準(zhǔn)測(cè)試,抑或是根據(jù)設(shè)備制造商、用戶代理(User Agent)字符串等其他因素間接推測(cè)設(shè)備能力。

但現(xiàn)在,有以下兩種方法可以直接或間接確定設(shè)備的大致RAM量:

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

值是 0.250.51248之一,所以機(jī)器 16G內(nèi)存,顯示的也是8。

Barcode Detection API[41]

用于檢測(cè)圖像中的條形碼和二維碼。

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

截圖_20245712025755.png

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

// 創(chuàng)建新檢測(cè)器
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從根本上改變了開發(fā)者在JavaScript中處理CSS屬性的方式,通過引入類型安全性和效率優(yōu)化。

比如:簡(jiǎn)簡(jiǎn)單單就能獲取樣式的鍵值對(duì), 其實(shí)還有一個(gè)結(jié)果有類似功能API?window.getComputedStyle

本文章轉(zhuǎn)載微信公眾號(hào)@成長(zhǎng)的程序世界

上一篇:

LLM Agent之結(jié)構(gòu)化輸出

下一篇:

Requests:API調(diào)用界的優(yōu)雅紳士,告別復(fù)雜的HTTP請(qǐng)求!
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)