溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么調(diào)優(yōu)jQuery的性能

發(fā)布時(shí)間:2022-03-31 10:35:27 來(lái)源:億速云 閱讀:138 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“怎么調(diào)優(yōu)jQuery的性能”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)建性能測(cè)試

關(guān)于性能測(cè)試的第一步是創(chuàng)建一個(gè)合適的性能測(cè)試。jQuery 以及其他 JavaScript 庫(kù)在代碼中扮演的最重要角色就是使用選擇查找特定頁(yè)面元素。我在最初的性能測(cè)試中就以這方面為重點(diǎn)。一個(gè)良好的性能測(cè)試應(yīng)該真正地發(fā)揮 JavaScript 庫(kù)的全部力量,用包含數(shù)千個(gè)頁(yè)面元素的頁(yè)面測(cè)試它。應(yīng)該運(yùn)行所有選擇方法,讓我看到哪個(gè)選擇方法最快,哪個(gè)最慢。測(cè)試應(yīng)該事先知道正確的答案,從而確定 JavaScript 庫(kù)是否正確地執(zhí)行選擇方法。最后,應(yīng)該顯示所有結(jié)果,并附帶所用的運(yùn)行時(shí)間,讓我能夠在所有庫(kù)之間進(jìn)行比較。

我差點(diǎn)忽略了性能測(cè)試的最重要方面:它應(yīng)該是免費(fèi)的。畢竟這個(gè)系列文章的不成文規(guī)則就是相互利用彼此的成果,因此我繼續(xù)發(fā)揚(yáng)這種精神,在此使用一個(gè)現(xiàn)成的 JavaScript 庫(kù)性能測(cè)試。這個(gè)測(cè)試稱為 SlickSpeed Selectors Test(見(jiàn) 參考資料),它非常適合我的需求。它將 jQuery 1.2.6(撰寫(xiě)本文時(shí)的最新版本)與其他 4 個(gè)流行的 JavaScript 庫(kù)(MooTools、Prototype、YUI 和 Dojo)進(jìn)行比較。然后,它使用帶有數(shù)千個(gè)頁(yè)面元素的頁(yè)面運(yùn)行40個(gè)選擇測(cè)試。換句話說(shuō),這是我所希望的最佳性能測(cè)試。我將在第一個(gè)性能測(cè)試分析中使用該測(cè)試。

對(duì)比JavaScript 庫(kù)的性能

對(duì)于第一個(gè)性能測(cè)試,我使用的運(yùn)行環(huán)境是 2.2 GHz 處理器、2 GB RAM 和 Firefox 3.0.3(非常重要)。我在該配置下運(yùn)行 5 次測(cè)試,圖 1 顯示了 5 次運(yùn)行的平均結(jié)果。

圖 1. 性能測(cè)試 1 的結(jié)果

怎么調(diào)優(yōu)jQuery的性能

從第一次測(cè)試能夠得出什么結(jié)論?現(xiàn)在我們僅關(guān)注總體結(jié)果,而不是每次測(cè)試。在獲得一些總體結(jié)論之后,我將稍后在本文中關(guān)注每個(gè)測(cè)試。

◆  結(jié)論 1:YUI 慢到了極點(diǎn)!

對(duì),與其他庫(kù)相比,YUI 真的很慢。仔細(xì)查看每個(gè)測(cè)試,找出為什么這個(gè)庫(kù)在選擇元素組(例如 “p, a”)時(shí)非常慢。對(duì)于要求具有很好性能的頁(yè)面而言,這個(gè)庫(kù)是最差的選擇。

◆  結(jié)論 2:Mootools、jQuery 和 Dojo 的運(yùn)行時(shí)間幾乎一樣。

與其他兩個(gè)庫(kù)相比,這 3 個(gè)庫(kù)是非??斓?,并且 Dojo 是它們當(dāng)中最快的,而 jQuery 是最慢的。但是從全局考慮,它們之間的速度是很接近的。

◆  結(jié)論 3:這些庫(kù)之間的相對(duì)差別還是比較明顯的。

度量最快時(shí)間/最慢時(shí)間以確定速度的相對(duì)差別,您可以看到相對(duì)差別為 332%。這個(gè)差別是比較大的,這表明使用 Firefox 時(shí)選擇不同的 JavaScript 庫(kù)會(huì)對(duì)性能有影響。

但是要記住,這些結(jié)論僅基于一個(gè)瀏覽器的結(jié)果。這是基于 Firefox 3.0.3 得出的結(jié)論?,F(xiàn)在我們進(jìn)入下一小節(jié),我將在不同的瀏覽器上運(yùn)行該測(cè)試。

在不同瀏覽器上的JavaScript 性能

面對(duì)不同瀏覽器運(yùn)行 JavaScript 會(huì)得出的不同結(jié)果(性能和時(shí)間都不同),許多初級(jí) Web 程序員覺(jué)得不可思議。盡管這對(duì)初級(jí) Web 程序員而言是個(gè)挫折(他們擔(dān)心要編寫(xiě)額外的代碼來(lái)處理不同的瀏覽器),但是有經(jīng)驗(yàn)的 Web 程序員在 Netscape 和 Internet Explorer 的早期就知道如何處理該問(wèn)題。這也是使用 JavaScript 庫(kù)的一個(gè)亮點(diǎn),因?yàn)樗鼈兌贾?jǐn)慎處理許多或大部分瀏覽器差異。

JavaScript 速度差異的主要原因是每個(gè)瀏覽器都使用自己的 JavaScript 引擎。JavaScript 引擎是用于解析 JavaScript 并根據(jù) Web 應(yīng)用程序執(zhí)行它的本機(jī)代碼。因此,JavaScript 的執(zhí)行速度與底層引擎直接相關(guān)。在最近幾個(gè)月,許多瀏覽器公司越來(lái)越關(guān)注他們的瀏覽器的性能,這是有原因的。隨著某些頁(yè)面的 JavaScript 變得日益復(fù)雜,JavaScript 引擎的快慢能夠影響 Web 應(yīng)用程序的響應(yīng)速度。因此,當(dāng) Google 和 Firefox 等公司談?wù)撍鼈兊?JavaScript 引擎時(shí),它們就會(huì)談及下一代引擎的速度要快 10 倍。這對(duì) Web 應(yīng)用程序而言是很重要的,因?yàn)榈讓?JavaScript 引擎的速度直接導(dǎo)致更復(fù)雜的 Web 應(yīng)用程序的出現(xiàn)。

現(xiàn)在,您知道 JavaScript 引擎是 JavaScript 執(zhí)行速度的一個(gè)因素,那么讓我們?cè)诓煌臑g覽器上運(yùn)行剛才在 Firefox 上運(yùn)行的測(cè)試,并嘗試找出不同的引擎對(duì) JavaScript 性能的影響。記住,這個(gè)測(cè)試與我前面在 Firefox 上運(yùn)行的測(cè)試是一樣的,因此除了 JavaScript 引擎以外,其他所有東西都是相同的。圖 2 顯示了測(cè)試結(jié)果。

圖 2. 性能測(cè)試 2 的結(jié)果

怎么調(diào)優(yōu)jQuery的性能

看完這些測(cè)試結(jié)果之后,您首先注意到的是在這些瀏覽器中運(yùn)行得到的時(shí)間差很大。在 Chrome 1.0 上運(yùn)行 jQuery 需要 168 毫秒,而在 IE6 上運(yùn)行需要 1728 秒。這是難以置信的時(shí)間差!jQuery 選擇方法在 IE6 上運(yùn)行比在 Chrome 上運(yùn)行慢 10 倍!現(xiàn)在,您知道為什么 Google 喜歡夸耀它的 JavaScript 引擎,以及為什么某些瀏覽器很少介紹自己的 JavaScript 引擎。這些差別還是比較大的。

您應(yīng)該注意到,jQuery 在 Firefox 或一些其他瀏覽器上運(yùn)行時(shí)速度排在第 3 位,而在另一些瀏覽器上排在第 1 位。事實(shí)上,這些結(jié)果表明,根據(jù)性能進(jìn)行分類(lèi)的話,這些庫(kù)可以分為兩組,而不管使用什么瀏覽器。Mootools、Dojo 和 jQuery 通常屬于一個(gè)組別,而 Prototype 和 YUI 屬于另一個(gè)組別,前一組要比后一組快得多。

性能測(cè)試結(jié)論

我覺(jué)得所有這些結(jié)論都需要專門(mén)花一個(gè)小節(jié)進(jìn)行闡述,因?yàn)樗鼈儗?duì) JavaScript 開(kāi)發(fā)人員非常重要。我仍然嘗試總結(jié)上面的性能結(jié)果,并且沒(méi)有忘記本文是以 jQuery 為主題的。

◆ 結(jié)論 1:Mootools、jQuery 和 Dojo 在性能方面不分上下。

查看它們?cè)谒?5 個(gè)瀏覽器上進(jìn)行的測(cè)試,在求取平均值之后,您可以看到這 3 個(gè)庫(kù)的性能幾乎是一樣的。(理想情況下,我們應(yīng)該調(diào)查每個(gè)瀏覽器的市場(chǎng)份額。但是調(diào)整這些數(shù)字很難,因?yàn)槭褂?JavaScript 庫(kù)的站點(diǎn)不一定由 “平均用戶” 訪問(wèn))。

圖 3. 測(cè)試結(jié)果的平均值(Mootools、jQuery 和 Dojo)

怎么調(diào)優(yōu)jQuery的性能


◆ 結(jié)論 2:Prototype 和 YUI 的性能很慢。

看看這兩個(gè)庫(kù)在 5 個(gè)瀏覽器中的測(cè)試結(jié)果與 jQuery 的對(duì)比。在求取它們的平均值之后,您可以發(fā)現(xiàn)這兩個(gè)庫(kù)的性能差別有多大。它們?cè)谌我鉃g覽器中平均比 jQuery 慢 300%。

圖 4. 測(cè)試結(jié)果的平均值(jQuery、Prototype 和 YUI)

怎么調(diào)優(yōu)jQuery的性能


◆ 結(jié)論 3:如果對(duì)性能要求比較高時(shí),選擇 Mootools、jQuery 和 Dojo 之一獲得的性能幾乎一樣。

根據(jù)以上的平均值,選擇這 3 個(gè)庫(kù)之一比選擇另外兩個(gè)庫(kù)之一能夠獲得更多的性能優(yōu)勢(shì)。從在所有瀏覽器上運(yùn)行得出的平均值看,它們的性能是相當(dāng)?shù)?。因此,?dāng)您選擇 JavaScript 庫(kù)時(shí),選擇這 3 個(gè)庫(kù)之一是不會(huì)錯(cuò)的。

◆ 結(jié)論 4:如果對(duì)性能要求比較高時(shí),不要選擇 Prototype 或 YUI。

如果要求 JavaScript 庫(kù)具有較高的性能,或者打算創(chuàng)建一個(gè)大型的 JavaScript 項(xiàng)目,那么就不應(yīng)該選擇這兩個(gè)庫(kù)之一。這兩個(gè)庫(kù)的性能要比其他庫(kù)遜色得多。

◆ 結(jié)論 5:瀏覽器對(duì)性能的影響是 JavaScript 庫(kù)的 9 倍。

我認(rèn)為這是本文所有結(jié)論中最重要的結(jié)論。您可以在特定情況下討論哪個(gè) JavaScript 庫(kù)最快,但它最終的影響卻是很小的!對(duì)于性能而言,瀏覽器的影響比庫(kù)本身要大得多?;仡櫼幌聢D 3 和圖 4 的平均值,您可以看到 3 個(gè)最快的庫(kù)中,最慢那個(gè)(Dojo)僅比最快那個(gè)(jQuery)慢 15%。只有 15%!然而,您看看 jQuery 在最快的瀏覽器(Chrome 1.0)和最慢的瀏覽器(IE6)上運(yùn)行的速度差別,這個(gè)差別竟然達(dá)到 1000%!從這兩個(gè)數(shù)字看,15% 對(duì) 1000% 而言是微不足道的。至此,關(guān)于 3 個(gè)較快的庫(kù)中哪個(gè)是最快的爭(zhēng)論可以停止了,因?yàn)樗鼈儗?duì)最終結(jié)果的影響是微乎其微的。

◆ 結(jié)論 6:如果 JavaScript 性能對(duì) Web 應(yīng)用程序很重要,并且您可以控制選擇什么瀏覽器,那么就選擇最快的瀏覽器!

在某些情況下,您可以控制使用什么瀏覽器訪問(wèn)站點(diǎn)。如果能夠控制使用什么瀏覽器,那么您就是很幸運(yùn)的。我就碰到這樣幸運(yùn)的項(xiàng)目。在這種情況下,如果您擁有一個(gè)復(fù)雜的 JavaScript 應(yīng)用程序,或者您認(rèn)為性能很重要,那么您就應(yīng)該控制用戶用于訪問(wèn) Web 應(yīng)用程序的瀏覽器。這些測(cè)試已經(jīng)清楚地顯示了瀏覽器的影響。如果您的 JavaScript 應(yīng)用程序的訪問(wèn)量很大,那么您可以告訴用戶,他們必須 使用 Chrome。

◆ 結(jié)論 7:如果您不能控制用戶使用的瀏覽器,那么要首先考慮在 IE6 上的性能。

但是,在大部分情況下,我們都無(wú)法控制用戶使用什么瀏覽器訪問(wèn)我們的站點(diǎn)。不過(guò),很大一部分用戶都使用 IE 6 瀏覽網(wǎng)頁(yè)。到目前為止的測(cè)試中,這個(gè)瀏覽器的 JavaScript 引擎是最慢的。但是由于仍然有大量用戶使用它,并且良好的 Web 設(shè)計(jì)需要 “適應(yīng)最糟糕的情況”,這意味著您可以考慮根據(jù) IE6 設(shè)計(jì)您的 JavaScript 應(yīng)用程序。

jQuery 性能調(diào)優(yōu)

本文的第二部分將討論如何改進(jìn) jQuery 代碼的性能。前一部分表明選擇 jQuery 作為 JavaScript 庫(kù)指向了正確的性能方向。如果您正在閱讀本文,您可能已經(jīng)使用了 jQuery。但是底層庫(kù)速度快并不意味著您編寫(xiě)的所有代碼都是高質(zhì)量的。如果您沒(méi)有回過(guò)頭來(lái)想想應(yīng)該怎么做,使用 jQuery 仍然會(huì)編寫(xiě)出非常慢的代碼。

這個(gè)部分介紹一些性能調(diào)優(yōu)知識(shí),以及改進(jìn) jQuery 代碼速度的最佳實(shí)踐技巧。

技巧 #1 - 盡可能多地通過(guò) ID 進(jìn)行搜索,而不是 CLASS

在 jQuery 代碼中兩種常見(jiàn)的搜索技術(shù)是通過(guò)元素的 ID 進(jìn)行搜索和通過(guò)元素的 CLASS 進(jìn)行搜索。在使用常規(guī) JavaScript 的 JavaScript 庫(kù)之前,通過(guò) ID 查找頁(yè)面元素還是相當(dāng)簡(jiǎn)單的??梢允褂?getElementById() 方法快速找到元素。但是如果沒(méi)有 JavaScript 庫(kù),要查找 CLASS 會(huì)更加困難,在必要情況下,我們還通過(guò)在其 ID 中進(jìn)行編碼幫助查找。使用 jQuery 時(shí),搜索 CLASS 就像搜索頁(yè)面上的 ID 一樣簡(jiǎn)單,因此這兩個(gè)搜索似乎是可互換的。然而實(shí)際情況并非如此。通過(guò) ID 搜索比通過(guò) CLASS 搜索要快得多。當(dāng)通過(guò) ID 進(jìn)行搜索時(shí),jQuery 實(shí)際上僅使用內(nèi)置的 getElementById() 方法,但通過(guò) CLASS 進(jìn)行搜索時(shí)必須遍歷頁(yè)面上的所有元素,以查找匹配項(xiàng)。很明顯,當(dāng)頁(yè)面越大并且越復(fù)雜時(shí),通過(guò) CLASS 進(jìn)行搜索會(huì)導(dǎo)致響應(yīng)非常慢,而通過(guò) ID 進(jìn)行搜索不會(huì)隨著頁(yè)面變大而變慢。

前面運(yùn)行的 jQuery 性能測(cè)試結(jié)果支持這一數(shù)據(jù)。讓我們查看每個(gè)測(cè)試,看看需要注意 jQuery 代碼的什么地方。在這個(gè)例子中,分別看看通過(guò) ID 和 CLASS 進(jìn)行搜索時(shí)的測(cè)試結(jié)果(圖 5)。

圖 5. ID 搜索和 CLASS 搜索對(duì)比

怎么調(diào)優(yōu)jQuery的性能


這些測(cè)試是不同的,但它們得出的數(shù)據(jù)表明通過(guò) ID 進(jìn)行搜索比通過(guò) CLASS 進(jìn)行搜索快得多。這如何影響到 jQuery 代碼?在編寫(xiě)搜索時(shí),您要記住這些技巧:如果既可選擇 CLASS 又可選擇 ID,那么通常要選擇 ID。如果需要在您的代碼中搜索某些元素,一定要給它們分配 ID。

清單 1 顯示了一個(gè)實(shí)際的 jQuery 測(cè)試,您可以在您的機(jī)器上運(yùn)行它對(duì)此進(jìn)行驗(yàn)證:

清單 1. CLASS 和 ID

$(document).ready(function() {     console.info("Start Test");    var d = new Date();    console.info(d.getSeconds() + " " + d.getMilliseconds());     var testBody = "";    for (var i=0; i<1000; i++)    {       testBody += "<div class='testable"+i+"'>";    }    $("body").append(testBody);    for (var i=0; i<1000; i++)    {      $(".testable"+i);    }     var d = new Date();    console.info(d.getSeconds() + " " + d.getMilliseconds());    console.time("Start ID Test");     testBody = "";    for (var i=0; i<1000; i++)    {      testBody += "<div id='testable"+i+"'>";    }    $("body").append(testBody);    for (var i=0; i<1000; i++)    {      $("#testable"+i);    }    var d = new Date();    console.info(d.getSeconds() + " " + d.getMilliseconds());    console.info("End Test");    });

ID 測(cè)試耗時(shí) 218 毫秒,而 CLASS 測(cè)試耗時(shí) 19.9 秒!甚至在專門(mén)為該測(cè)試構(gòu)建的簡(jiǎn)單頁(yè)面上,ID 搜索也要比 CLASS 搜索快 100 倍!

技巧 #2 - 提供盡可能多的搜索信息

jQuery 提供如此多的頁(yè)面元素搜索方法,有時(shí)您難以指出哪種方法是最好的。有一條經(jīng)驗(yàn)是不會(huì)錯(cuò)的,即為搜索參數(shù)提供盡可能多的信息。因此,假如您正在搜索帶有 “clickable” CLASS 的所有頁(yè)面元素,如果您提前知道僅有 DIV 附帶有 CLASS,那么就能提高搜索性能。所以,搜索 “div.clickable” 會(huì)更加快。圖 6 顯示了支持該技巧的結(jié)果。

圖 6. 盡可能多地提供信息

怎么調(diào)優(yōu)jQuery的性能


考慮到底層 JavaScript 代碼之后,這就不足為奇了。通過(guò)提供元素標(biāo)記,與 CLASS 參數(shù)匹配的搜索元素?cái)?shù)量將大大減少,從而將搜索性能提升至與本例中的 ID 搜索相當(dāng)。

開(kāi)發(fā)人員在編寫(xiě) jQuery 選擇方法時(shí)不能偷懶,盡管 jQuery 的簡(jiǎn)單讓人產(chǎn)生偷懶的欲望。簡(jiǎn)單讓您放松了警惕。搜索機(jī)制變得如此簡(jiǎn)單,讓我們傾向于僅輸入一條信息。然而,您應(yīng)該總是盡可能多地輸入信息,尤其是已知信息。清單 2 顯示了一個(gè)很好的例子。

清單 2. 提供充足的信息

// Assume there are 50 of these in some giant form, and you need to validate  // these fields before they are submitted, and there are hundreds of other  // elements on the page as well  <input type=text class="notBlank">   // the "bad" way to validate these fields  $(".notBlank").each(function(){     if ($(this).val()=="")        $(this).addClass("error");  });   // the "good" way to validate these fields  $("input.notBlank").each(function(){     if ($(this).val()=="")        $(this).addClass("error");  });   // the "best" way to validate these fields  $("input:text.notBlank").each(function(){     if ($(this).val()=="")        $(this).addClass("error");        });

技巧 #3 - 緩存選擇器

最后一個(gè)性能技巧利用了幾乎所有 jQuery 選擇器都返回 jQuery 對(duì)象這個(gè)特性。這意味著在理想的情況下,您僅需要運(yùn)行選擇器一次,并且能夠輕松地將所有函數(shù)連接在一起,或緩存結(jié)果供以后使用。您也不要擔(dān)心緩存,因?yàn)榕c總體可用內(nèi)存相比,返回的對(duì)象是很小的。

清單 3 給出了一些關(guān)于如何利用緩存的例子。

清單 3. 緩存

在我的最后一個(gè)關(guān)于性能

// Imagine a function that hides all the div's with a class of "hideable"   // when a button is pressed.  These DIV's might reappear later when   // working with the page,  so the button can be pressed any number of   // times, and the DIV's that have reappeared  // will again be made to be hidden.   $("#ourHideButton").click(function(){     $(".hideable").hide();  });   // As you saw in the CLASS versus ID example, though, a search for   // CLASS is very inefficient  // If this button is pressed often, it could lead to a slow response  // Instead of the above example, you should write your code like this   var hideable;   $("#ourHideButton").click(function(){     if (hideable)         hideable.hide();     else        hideable = $(".hideable").hide();  });   // You can cache your search in a JavaScript variable and reuse it every time  // the button is pressed.  Because jQuery almost always returns the  // jQuery object, you can save it the first time it is called for future use

的示例代碼中,將查看我在本系列的第一篇文章中提到的小部件(見(jiàn) 參考資料)。這個(gè)小部件是在表的左上角上的復(fù)選框,它允許您選擇或取消選擇該列上的所有復(fù)選框。這個(gè)小部件在電子郵件應(yīng)用程序中非常常見(jiàn),用于選擇或取消選擇所有消息。

清單 4. 性能改進(jìn)

// Here is the code as I originally presented it in that article.  Let's see  // if we can improve the performance in any way from the things we learned here   function selectAll()  {      var checked = $("#selectall").attr("checked");      $(".selectable").each(function(){         var subChecked = $(this).attr("checked");         if (subChecked != checked)            $(this).click();      });  }   // Here's the improved function.  The search for the ID of "selectall" is  // OK as-is, because we saw how fast the ID search is.  // The search for the CLASS of "selectable" was not well-designed though,  // because we saw a search by CLASS is very inefficient.  // First step was improving the search by supplying as much information as we know.  // We narrowed the search to only checkboxes with the CLASS of selectable.  // This should improve our search  // Further, we can cache this search because we will only need to perform it once  // Finally, we can perform this search before the selectall checkbox is even  // checked (when the page is finished loading), so that the search is completed  // and cached before the user even uses it.  // These 3 simple performance steps gave me a 200% increase in speed when tested  // on a page with 200 rows of data.   var selectable = $(":checkbox.selectable");  function selectAll()  {      var checked = $("#selectall").attr("checked");      selectable.each(function(){         var subChecked = $(this).attr("checked");         if (subChecked != checked)            $(this).click();      });  }

“怎么調(diào)優(yōu)jQuery的性能”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI