在單元測試真實世界代碼時,許多情況使測試難以編寫。如何檢查是否調用了函數?如何測試 Ajax 調用?或者使用 setTimeout
的代碼?這時,您需要使用 測試替身 —— 替換代碼,使難以測試的內容易於測試。
多年來,Sinon.js 一直是 JavaScript 測試中創建測試替身的實際標準。對於任何編寫測試的 JavaScript 開發人員來說,它都是必不可少的工具,因為沒有它,為真實應用程序編寫測試幾乎是不可能的。
最近,一個名為 testdouble.js 的新庫正在興起。它擁有與 Sinon.js 類似的功能集,只是這里和那裡有一些不同。
在本文中,我們將探討 Sinon.js 和 testdouble.js 提供的內容,並比較它們各自的優缺點。 Sinon.js 是否仍然是更好的選擇,或者挑戰者能否勝出?
注意:如果您不熟悉測試替身,建議您先閱讀我的 Sinon.js 教程。這將幫助您更好地理解我們將在此處討論的概念。
關鍵要點
- 功能集和術語:Sinon.js 提供了一套傳統的測試替身,包括間諜、存根和模擬,這對於精通其他編程語言的人來說很熟悉,而testdouble.js 簡化了術語,並專注於更以JavaScript 為中心的詞彙,消除了傳統的間諜。
- 易用性:Testdouble.js 擁有更簡單的API,初學者更容易掌握,而Sinon.js 提供了更詳細但更複雜的接口,熟悉其他語言中類似測試工具的用戶可能會更喜歡它。
- 處理輸入的功能:Sinon.js 允許在存根和斷言中更靈活地使用輸入參數,不一定需要完全匹配,這與 testdouble.js 除非明確配置,否則嚴格要求精確參數匹配形成對比。
- 對Promise 和回調的支持:Testdouble.js 集成了對Promise 的內置支持,並提供了強大的回調處理功能,與Sinon.js 相比,這可能更適合現代JavaScript 開發,Sinon.js 需要額外的配置才能實現類似的功能。
- 模塊替換功能:Testdouble.js 支持替換整個模塊,這有利於隔離測試模塊交互;此功能在 Sinon.js 中不可用,除非使用 proxyquire 或 rewire 等其他工具。
- 清理和維護:Testdouble.js 使用單個重置函數簡化了清理過程,從而減少了可能影響其他測試的剩餘測試替身的風險,而Sinon.js 提供了多種清理方法,管理起來可能更麻煩。
本文中使用的術語
為了確保易於理解正在討論的內容,以下是所用術語的快速概述。這些是 Sinon.js 的定義,在其他地方可能略有不同。
- 測試替身是測試期間使用的函數的替代品。它可以指下面提到的三種類型中的任何一種。
- 間諜是一種測試替身,它允許檢查效果而不影響目標函數的行為。
- 存根是一種測試替身,它用其他東西替換目標函數的行為,例如返回值。
- 模擬是一種與存根不同的方法。模擬包含內置驗證,可以替代單獨的斷言。
需要注意的是,testdouble.js 的目標之一是減少這種術語之間的混淆。
Sinon.js 和 testdouble.js 概述
讓我們首先看看 Sinon.js 和 testdouble.js 在基本用法上的比較。
Sinon 有三種不同的測試替身概念:間諜、存根和模擬。其思想是,每種都代表不同的使用場景。這使得該庫對於來自其他語言或閱讀過使用相同術語的書籍(例如 xUnit 測試模式)的人來說更加熟悉。但另一方面,這三種概念也可能使 Sinon 在首次使用時 更難 理解。
這是一個 Sinon 用法的基本示例:
// 以下是查看函数调用的参数的方法: var spy = sinon.spy(Math, 'abs'); Math.abs(-10); console.log(spy.firstCall.args); // 输出:[ -10 ] spy.restore(); // 以下是控制函数执行方式的方法: var stub = sinon.stub(document, 'createElement'); stub.returns('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' stub.restore();
相反,testdouble.js 選擇了一個更簡單的 API。它不使用間諜或存根之類的概念,而是使用 JavaScript 開發人員更熟悉的語言,例如 td.function
、td.object
和 td.replace
。這使得 testdouble 潛在地更容易上手,並且更適合某些任務。但另一方面,某些更高級的用途可能根本不可能實現(這有時是故意的)。
以下是 testdouble.js 的使用方法:
// 以下是查看函数调用的参数的方法: var abs = td.replace(Math, 'abs'); Math.abs(-10); var explanation = td.explain(abs); console.log(explanation.calls[0].args); // 输出:[ -10 ] // 以下是控制函数执行方式的方法: var createElement = td.replace(document, 'createElement'); td.when(createElement(td.matchers.anything())).thenReturn('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' // testdouble 使用一次调用重置所有测试替身,无需单独清理 td.reset();
testdouble 使用的語言更簡單。我們“替換”函數而不是“存根”它。我們要求 testdouble “解釋”函數以從中獲取信息。除此之外,到目前為止,它與 Sinon 相當相似。
這也擴展到創建“匿名”測試替身:
var x = sinon.stub();
與
var x = td.function();
Sinon 的間諜和存根具有提供有關它們的更多信息的屬性。例如,Sinon 提供了 stub.callCount
和 stub.args
等屬性。在 testdouble 的情況下,我們從 td.explain
獲取此信息:
// 我们也可以为测试替身命名 var x = td.function('hello'); x('foo', 'bar'); td.explain(x); console.log(x); /* 输出: { name: 'hello', callCount: 1, calls: [ { args: ['foo', 'bar'], context: undefined } ], description: 'This test double `hello` has 0 stubbings and 1 invocations.\n\nInvocations:\n - called with `("foo", "bar")`.', isTestDouble: true } */
較大的區別之一與設置存根和驗證的方式有關。使用 Sinon,您可以在存根之後鏈接命令,並使用斷言來驗證結果。 testdouble.js 只需向您展示您希望如何調用函數——或者如何“排練”函數調用。
var x = sinon.stub(); x.withArgs('hello', 'world').returns(true); var y = sinon.stub(); sinon.assert.calledWith(y, 'foo', 'bar');
與
var x = td.function(); td.when(x('hello', 'world')).thenReturn(true); var y = td.function(); td.verify(y('foo', 'bar'));
這使得 testdouble 的 API 更易於理解,因為您不需要知道可以在何時鏈接哪些操作。
更詳細地比較常見的測試任務
在高層次上,這兩個庫都相當相似。但是您可能需要在實際項目中執行的常見測試任務呢?讓我們看看一些差異開始顯現的情況。
testdouble.js 沒有間諜
首先要注意的是,testdouble.js 沒有“間諜”的概念。雖然 Sinon.js 允許我們替換函數調用以便從中獲取信息,同時保留函數的默認行為,但這在 testdouble.js 中根本不可能。當您使用 testdouble 替換函數時,它總是會丟失其默認行為。
但這不一定是問題。間諜最常見的用法是使用它們來驗證是否調用了回調,這很容易使用 td.function
來完成:
var spy = sinon.spy(); myAsyncFunction(spy); sinon.assert.calledOnce(spy);
與
var spy = td.function(); myAsyncFunction(spy); td.verify(spy());
雖然不是什麼大問題,但仍然需要注意這兩個庫之間的這種差異,否則如果您期望能夠以某種更具體的方式使用 testdouble.js 中的間諜,您可能會感到驚訝。
testdouble.js 需要更精確的輸入
您會遇到的第二個區別是 testdouble 對輸入更嚴格。
Sinon 的存根和斷言都允許您對提供的參數不精確。這最容易通過示例來說明:
var stub = sinon.stub(); stub.withArgs('hello').returns('foo'); console.log(stub('hello', 'world')); // 输出:'foo' sinon.assert.calledWith(stub, 'hello'); // 没有错误
與
// 以下是查看函数调用的参数的方法: var spy = sinon.spy(Math, 'abs'); Math.abs(-10); console.log(spy.firstCall.args); // 输出:[ -10 ] spy.restore(); // 以下是控制函数执行方式的方法: var stub = sinon.stub(document, 'createElement'); stub.returns('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' stub.restore();
默認情況下,Sinon 不關心向函數提供了多少額外參數。雖然它提供了諸如 sinon.assert.calledWithExactly
之類的函數,但在文檔中並不建議將其作為默認值。像 stub.withArgs
這樣的函數也沒有“exactly”變體。
另一方面,testdouble.js 默認情況下要求指定精確的參數。這是設計使然。其思想是,如果向函數提供了一些在測試中未指定的其他參數,則這可能是一個錯誤,並且應該使測試失敗。
可以在 testdouble.js 中允許指定任意參數,但這並不是默認值:
// 以下是查看函数调用的参数的方法: var abs = td.replace(Math, 'abs'); Math.abs(-10); var explanation = td.explain(abs); console.log(explanation.calls[0].args); // 输出:[ -10 ] // 以下是控制函数执行方式的方法: var createElement = td.replace(document, 'createElement'); td.when(createElement(td.matchers.anything())).thenReturn('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' // testdouble 使用一次调用重置所有测试替身,无需单独清理 td.reset();
使用 ignoreExtraArgs: true
,行為類似於 Sinon.js。
testdouble.js 具有內置 Promise 支持
雖然使用 Sinon.js 的 Promise 並不復雜,但 testdouble.js 具有返回和拒絕 Promise 的內置方法。
var x = sinon.stub();
與
var x = td.function();
注意:可以使用 sinon-as-promised 在 Sinon 1.x 中包含類似的便捷函數。 Sinon 2.0 和更新版本以 stub.resolves
和 stub.rejects
的形式包含 Promise 支持。
testdouble.js 的回調支持更強大
Sinon 和 testdouble 都提供了一種簡單的方法來讓存根函數調用回調。但是,它們在工作方式上有一些差異。
Sinon 使用 stub.yields
來讓存根調用它作為參數接收的 第一個函數。
// 我们也可以为测试替身命名 var x = td.function('hello'); x('foo', 'bar'); td.explain(x); console.log(x); /* 输出: { name: 'hello', callCount: 1, calls: [ { args: ['foo', 'bar'], context: undefined } ], description: 'This test double `hello` has 0 stubbings and 1 invocations.\n\nInvocations:\n - called with `("foo", "bar")`.', isTestDouble: true } */
testdouble.js 默認使用 Node 樣式模式,其中回調被假定為 最後一個 參數。在排練調用時,您也不必指定它:
var x = sinon.stub(); x.withArgs('hello', 'world').returns(true); var y = sinon.stub(); sinon.assert.calledWith(y, 'foo', 'bar');
使 testdouble 的回調支持更強大的原因是您可以輕鬆定義具有多個回調或回調順序不同的場景的行為。
假設我們想調用 callback1
……
var x = td.function(); td.when(x('hello', 'world')).thenReturn(true); var y = td.function(); td.verify(y('foo', 'bar'));
請注意,我們將 td.callback
作為參數傳遞給 td.when
中的函數。這告訴 testdouble 我們希望使用哪個參數作為回調。
使用 Sinon,也可以更改行為:
var spy = sinon.spy(); myAsyncFunction(spy); sinon.assert.calledOnce(spy);
在這種情況下,我們使用 callsArgWith
而不是 yields
。我們必須提供調用的特定索引才能使其工作,這可能有點麻煩,尤其是在具有許多參數的函數上。
如果我們想使用某些值調用 兩個 回調呢?
var spy = td.function(); myAsyncFunction(spy); td.verify(spy());
使用 Sinon,這根本不可能。您可以鏈接對 callsArgWith
的多次調用,但它只會調用其中一個。
testdouble.js 具有內置模塊替換
除了能夠使用 td.replace
替換函數之外,testdouble 還允許您替換整個模塊。
這主要在您有一個直接導出需要替換的函數的模塊的情況下有用:
var stub = sinon.stub(); stub.withArgs('hello').returns('foo'); console.log(stub('hello', 'world')); // 输出:'foo' sinon.assert.calledWith(stub, 'hello'); // 没有错误
如果我們想用 testdouble 替換它,我們可以使用 td.replace('path/to/file')
,例如……
// 以下是查看函数调用的参数的方法: var spy = sinon.spy(Math, 'abs'); Math.abs(-10); console.log(spy.firstCall.args); // 输出:[ -10 ] spy.restore(); // 以下是控制函数执行方式的方法: var stub = sinon.stub(document, 'createElement'); stub.returns('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' stub.restore();
雖然 Sinon.js 可以替換某個對象的成員函數,但它不能像這樣替換模塊。在使用 Sinon 時要執行此操作,您需要使用另一個模塊,例如 proxyquire 或 rewire。
// 以下是查看函数调用的参数的方法: var abs = td.replace(Math, 'abs'); Math.abs(-10); var explanation = td.explain(abs); console.log(explanation.calls[0].args); // 输出:[ -10 ] // 以下是控制函数执行方式的方法: var createElement = td.replace(document, 'createElement'); td.when(createElement(td.matchers.anything())).thenReturn('not an html element'); var x = document.createElement('div'); console.log(x); // 输出:'not an html element' // testdouble 使用一次调用重置所有测试替身,无需单独清理 td.reset();
關於模塊替換需要注意的另一件事是 testdouble.js 會自動替換整個模塊。如果它像這裡的示例一樣是函數導出,它會替換該函數。如果它是一個包含多個函數的對象,它會替換所有這些函數。構造函數和 ES6 類也受支持。 proxyquire 和 rewire 都要求您單獨指定要替換的內容和方式。
testdouble.js 缺少 Sinon 的一些輔助函數
如果您使用 Sinon 的模擬計時器、模擬 XMLHttpRequest 或模擬服務器,您會注意到它們在 testdouble 中不存在。
模擬計時器可以作為插件使用,但 XMLHttpRequests 和 Ajax 功能需要以不同的方式處理。
一個簡單的解決方案是替換您正在使用的 Ajax 函數,例如 $.post
:
var x = sinon.stub();
使用 testdouble.js 更容易清理測試後的內容
對於 Sinon.js 的初學者來說,一個常見的絆腳石往往是清理間諜和存根。 Sinon 提供了 三種 不同的方法來做到這一點,這並沒有什麼幫助。
var x = td.function();
或:
// 我们也可以为测试替身命名 var x = td.function('hello'); x('foo', 'bar'); td.explain(x); console.log(x); /* 输出: { name: 'hello', callCount: 1, calls: [ { args: ['foo', 'bar'], context: undefined } ], description: 'This test double `hello` has 0 stubbings and 1 invocations.\n\nInvocations:\n - called with `("foo", "bar")`.', isTestDouble: true } */
或:
var x = sinon.stub(); x.withArgs('hello', 'world').returns(true); var y = sinon.stub(); sinon.assert.calledWith(y, 'foo', 'bar');
通常情況下,建議使用 sandbox 和 sinon.test
方法,否則很容易意外地留下存根或間諜,這可能會導致其他測試出現問題。這可能會導致難以追踪的級聯故障。
testdouble.js 只提供了一種清理測試替身的方法:td.reset()
。推薦的方法是在 afterEach
鉤子中調用它:
var x = td.function(); td.when(x('hello', 'world')).thenReturn(true); var y = td.function(); td.verify(y('foo', 'bar'));
這極大地簡化了測試替身的設置和測試後的清理,降低了難以追踪的錯誤的可能性。
優缺點
我們現在已經了解了這兩個庫的功能。它們都提供了一套相當類似的功能集,但它們彼此的設計理念有所不同。我們能否將其分解為優缺點?
讓我們首先談談 Sinon.js。它提供了一些比 testdouble.js 更多的附加功能,並且它的一些方面更易於配置。這為它在更特殊的測試場景中提供了一些更高的靈活性。 Sinon.js 還使用更熟悉其他語言的人的語言——間諜、存根和模擬等概念存在於不同的庫中,並且也在測試相關的書籍中討論過。
缺點是增加了複雜性。雖然它的靈活性允許專家做更多的事情,但這意味著某些任務比在 testdouble.js 中更複雜。對於那些剛接觸測試替身概念的人來說,它也可能具有更陡峭的學習曲線。事實上,即使像我這樣非常熟悉它的人也可能難以詳細說明 sinon.stub
和 sinon.mock
之間的某些區別!
testdouble.js 選擇了一個更簡單的接口。它的大部分內容都相當簡單易用,並且感覺更適合 JavaScript,而 Sinon.js 有時感覺像是為其他語言設計的。由於這一點及其一些設計原則,它對於初學者來說更容易上手,即使是經驗豐富的測試人員也會發現許多任務更容易完成。例如,testdouble 使用相同的 API 來設置測試替身和驗證結果。由於其更簡單的清理機制,它也可能更不容易出錯。
testdouble 最大的問題是由它的一些設計原則造成的。例如,完全缺乏間諜可能會使某些更喜歡使用間諜而不是存根的人無法使用它。這在很大程度上是一個意見問題,您可能根本不會發現問題。除此之外,儘管 testdouble.js 是一個更新的庫,但它正在為 Sinon.js 提供一些嚴重的競爭。
按功能比較
以下是按功能的比較:
功能 | Sinon.js | testdouble.js |
---|---|---|
间谍 | 是 | 否 |
存根 | 是 | 是 |
延迟存根结果 | 否 | 是 |
模拟 | 是 | 是1 |
Promise 支持 | 是(在 2.0 中) | 是 |
时间辅助函数 | 是 | 是(通过插件) |
Ajax 辅助函数 | 是 | 否(改为替换函数) |
模块替换 | 否 | 是 |
内置断言 | 是 | 是 |
匹配器 | 是 | 是 |
自定义匹配器 | 是 | 是 |
参数捕获器 | 否2 | 是 |
代理测试替身 | 否 | 是 |
- testdouble.js 從技術上講 沒有 Sinon.js 中那樣的模擬。但是,由於 Sinon 中的模擬本質上是包含存根和驗證的對象,因此可以通過使用
td.replace(someObject)
來實現類似的效果。 - 可以通過使用
stub.yield
(不要與stub.yields
混淆)來實現與參數捕獲器類似的效果。
總結和結論
Sinon.js 和 testdouble.js 都提供了一套相當類似的功能。在這方面,兩者都不明顯優越。
兩者之間最大的區別在於它們的 API。 Sinon.js 可能稍微冗長一些,同時提供了許多關於如何做事情的選項。這可能是它的優點和缺點。 testdouble.js 具有更精簡的 API,這使其更容易學習和使用,但由於其更武斷的設計,有些人可能會發現它有問題。
那麼哪個適合我?
您是否同意 testdouble 的設計原則?如果是,那麼沒有理由不使用它。我在許多項目中都使用過 Sinon.js,我可以肯定地說 testdouble.js 至少完成了我在 Sinon.js 中完成的 95% 的工作,其餘 5% 可能可以通過一些簡單的解決方法來完成。
如果您發現 Sinon.js 難以使用,或者正在尋找更“JavaScript 式”的測試替身方法,那麼 testdouble.js 也可能適合您。即使像我這樣花了很多時間學習使用 Sinon 的人,我也傾向於建議嘗試 testdouble.js 並看看您是否喜歡它。
但是,testdouble.js 的某些方面可能會讓那些了解 Sinon.js 或其他經驗豐富的測試人員頭疼。例如,完全缺乏間諜可能是決定性因素。對於專家和那些想要最大靈活性的用戶來說,Sinon.js 仍然是一個不錯的選擇。
如果您想了解更多關於如何在實踐中使用測試替身的信息,請查看我的免費 Sinon.js 實戰指南。雖然它使用 Sinon.js,但您也可以將相同的技術和最佳實踐應用於 testdouble.js。
有問題?評論?您是否已經在使用 testdouble.js 了?閱讀本文後,您是否會考慮嘗試一下?請在下面的評論中告訴我。
本文由 James Wright、Joan Yin、Christian Johansen 和 Justin Searls 共同評審。感謝所有 SitePoint 的同行評審者,使 SitePoint 內容達到最佳狀態!
關於 JavaScript 測試工具的常見問題:Sinon.js 與 Testdouble.js
Sinon.js 和 Testdouble.js 的主要區別是什麼?
Sinon.js 和 Testdouble.js 都是流行的 JavaScript 測試庫,但它們有一些關鍵區別。 Sinon.js 以其豐富的功能集而聞名,包括間諜、存根和模擬,以及用於模擬計時器和 XHR 的實用程序。它是一個多功能工具,可以與任何測試框架結合使用。另一方面,Testdouble.js 是一個極簡的庫,專注於為測試替身提供簡單直觀的 API,測試替身是待測系統部分的替代品。它不包括用於模擬計時器或 XHR 的實用程序,但它設計易於使用和理解,因此對於那些更喜歡更精簡的測試方法的人來說是一個不錯的選擇。
如何安裝 Sinon.js 和 Testdouble.js?
Sinon.js 和 Testdouble.js 都可以通過 npm(Node.js 包管理器)安裝。對於 Sinon.js,您可以使用命令 npm install sinon
。對於 Testdouble.js,命令是 npm install testdouble
。安裝後,您可以分別使用 const sinon = require('sinon')
和 const td = require('testdouble')
在您的測試文件中引入它們。
我可以同時使用 Sinon.js 和 Testdouble.js 嗎?
是的,可以在同一個項目中同時使用 Sinon.js 和 Testdouble.js。它們都設計得非常簡潔,並且可以很好地與其他庫一起工作。但是,請記住它們具有重疊的功能,因此同時使用它們可能會導致混淆。通常建議根據您的具體需求和偏好選擇其中一個。
如何使用 Sinon.js 和 Testdouble.js 創建間諜?
在 Sinon.js 中,您可以使用 sinon.spy()
創建間諜。此函數返回一個間諜對象,該對象記錄對其進行的所有調用,包括參數、返回值和異常。在 Testdouble.js 中,您可以使用 td.function()
創建間諜。此函數返回一個記錄所有調用的測試替身函數,包括參數。
如何使用 Sinon.js 和 Testdouble.js 創建存根?
在 Sinon.js 中,您可以使用 sinon.stub()
創建存根。此函數返回一個存根對象,其行為類似於間諜,但它還允許您定義其行為,例如指定返回值或拋出異常。在 Testdouble.js 中,您可以使用 td.when()
創建存根。此函數允許您在使用特定參數調用測試替身時定義其行為。
如何使用 Sinon.js 和 Testdouble.js 驗證間諜或存根?
在 Sinon.js 中,您可以使用 spy.called
、spy.calledWith()
和 spy.returned()
等方法來驗證間諜或存根。在 Testdouble.js 中,您可以使用 td.verify()
來斷言測試替身是否以某種方式被調用。
使用 Sinon.js 而不是 Testdouble.js 的優勢是什麼?
與 Testdouble.js 相比,Sinon.js 具有更全面的功能集。它包括用於模擬計時器和 XHR 的實用程序,這對於測試某些類型的代碼非常有用。它也更廣泛地使用,並且擁有更大的社區,這意味著可以獲得更多資源和支持。
使用 Testdouble.js 而不是 Sinon.js 的優勢是什麼?
與 Sinon.js 相比,Testdouble.js 具有更簡單直觀的 API。它設計易於使用和理解,因此對於那些更喜歡更精簡的測試方法的人來說是一個不錯的選擇。它還通過使濫用測試替身變得困難來鼓勵良好的測試實踐。
我可以將 Sinon.js 和 Testdouble.js 與其他測試框架一起使用嗎?
是的,Sinon.js 和 Testdouble.js 都設計得非常簡潔,並且可以很好地與其他測試框架一起工作。它們可以與任何支持 JavaScript 的測試框架一起使用。
有哪些資源可以學習更多關於 Sinon.js 和 Testdouble.js 的知識?
是的,Sinon.js 和 Testdouble.js 在其官方網站上都有大量的文檔。還有許多教程、博客文章和在線課程涵蓋了這些庫的深入內容。
以上是JavaScript測試工具攤牌:sinon.js vs testdouble.js的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

將矩陣電影特效帶入你的網頁!這是一個基於著名電影《黑客帝國》的酷炫jQuery插件。該插件模擬了電影中經典的綠色字符特效,只需選擇一張圖片,插件就會將其轉換為充滿數字字符的矩陣風格畫面。快來試試吧,非常有趣! 工作原理 插件將圖片加載到畫布上,讀取像素和顏色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地讀取圖片的矩形區域,並利用jQuery計算每個區域的平均顏色。然後,使用

本文將引導您使用jQuery庫創建一個簡單的圖片輪播。我們將使用bxSlider庫,它基於jQuery構建,並提供許多配置選項來設置輪播。 如今,圖片輪播已成為網站必備功能——一圖胜千言! 決定使用圖片輪播後,下一個問題是如何創建它。首先,您需要收集高質量、高分辨率的圖片。 接下來,您需要使用HTML和一些JavaScript代碼來創建圖片輪播。網絡上有很多庫可以幫助您以不同的方式創建輪播。我們將使用開源的bxSlider庫。 bxSlider庫支持響應式設計,因此使用此庫構建的輪播可以適應任何

數據集對於構建API模型和各種業務流程至關重要。這就是為什麼導入和導出CSV是經常需要的功能。在本教程中,您將學習如何在Angular中下載和導入CSV文件


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

WebStorm Mac版
好用的JavaScript開發工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載
最受歡迎的的開源編輯器