国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
硬編碼的背景顏色
討厭的控制臺日誌
攔截廣告服務器調用
JavaScript中的猴子補丁的概念是什麼?
JavaScript和Python中的猴子補丁有何不同?
猴子補丁在JavaScript中被認為是一種好的實踐嗎?
猴子補丁的潛在風險是什麼?
如何在JavaScript中乾淨地猴子補丁一個函數(shù)?
猴子補丁可以用於測試和調試嗎?
原型在JavaScript中的猴子補丁中起什麼作用?
猴子補丁如何影響JavaScript中的性能?
猴子補丁可以用來擴展內(nèi)置的JavaScript對象嗎?
JavaScript中猴子補丁的一些替代方案是什麼?
首頁 web前端 js教程 JavaScript中猴子補丁的務實用途

JavaScript中猴子補丁的務實用途

Feb 17, 2025 pm 12:52 PM

Pragmatic Uses of Monkey Patching in JavaScript

核心要點

  • JavaScript中的猴子補丁(MP)是一種技術,允許程序員覆蓋、擴展或抑制代碼段的默認行為,而無需更改其原始源代碼。
  • 雖然MP通常被認為是不好的實踐,但它可以作為修改第三方代碼以適應特定需求的有用工具,尤其是在無法更改原始源代碼的情況下。
  • MP可用於用自定義行為覆蓋現(xiàn)有函數(shù),通過在原始代碼之前或之後添加自定義行為來增強方法,或攔截Ajax調用以修改其行為。
  • 應該謹慎使用MP,因為它可能導致代碼中出現(xiàn)不可預測的行為和衝突,特別是如果在代碼庫的其他地方使用了已修補的方法。
  • 儘管存在潛在風險,但MP仍然可以成為測試、調試和實施修復的強大工具,它突出了JavaScript作為編程語言的靈活性和動態(tài)性。

Pragmatic Uses of Monkey Patching in JavaScript

本文由Moritz Kr?ger和Tom Greco審核。感謝所有SitePoint的同行評審員,使SitePoint的內(nèi)容達到最佳狀態(tài)!

您是否曾經(jīng)使用過第三方代碼,除了一個讓您抓狂的小問題外,其他都運行良好?創(chuàng)建者為什麼忘記刪除那些討厭的控制臺日誌?如果那個API調用可以多做一件事,那不是很好嗎?如果是這樣,那麼您就會知道,讓維護者實施您的更改可能很困難(或不可能)。但是,自己更改代碼呢?如果您沒有源代碼並且不想自己託管它們,該如何操作?歡迎來到JavaScript猴子補丁的世界之旅!

在本文中,我們將了解什麼是猴子補丁,並逐步完成一些不同的示例,使用它來更改第三方小部件的功能以適應我們的需求。

什麼是猴子補?。?

猴子補?。ㄒ韵潞喎QMP)是一種技術,用於覆蓋、擴展甚至抑制代碼段的默認行為,而無需更改其原始源代碼。這是通過用修復版本替換原始行為來實現(xiàn)的。

本文將使用現(xiàn)有的反饋框小部件,該小部件顯示一個簡單的、可滑動的彈出窗口(如下圖所示),其中包含反饋表單。

Pragmatic Uses of Monkey Patching in JavaScript

源代碼已修改為包含用作MP目標的用例。目標是指我們將要修補的特定功能、特性或最低級別的使用方法。

我做的另一個修改是刪除了圍繞代碼的立即調用函數(shù)表達式(IIFE)。這樣做是為了專注於MP的技術。

您可以在Plunker中找到整個示例,包括本文中討論的猴子補丁。

猴子補丁不是一種不好的實踐嗎?

在開始之前,讓我們先明確一點:是的,MP被認為是一種不好的實踐——邪惡的eval、命令式編程、可變數(shù)據(jù)結構、雙向綁定等等也是如此。

如果您使用其中任何一種,很可能會有相當大的一群人告訴您您做錯了,應該更改此或那項以適應更好的條件。但一如既往,有不同的工具和技術可用,它們在特定場景下的適用性各不相同。有時,看起來極端、瘋狂或根本不好的東西可能是特定情況下的最後手段。不幸的是,由於某些實踐被認為是不好的,您甚至找不到很多文章來描述如何以正確的方式做錯事。

此處描述的情況可能是不自然的,用虛假的小部件將其推向極端,以顯示您的選擇。然後,作為讀者,您必須決定是否喜歡您看到的內(nèi)容。如果沒有什麼別的,在閱讀本文之後,您將有更好的理解,以便反對MP。

猴子補丁的目標

在我們深入研究這些技術之前,讓我們首先檢查一下我們想要實現(xiàn)的目標。修改後的窗口部件有一些代碼異味,我們想解決這些問題。

硬編碼的背景顏色

第一個是名為toggleError的方法,該方法應該根據(jù)布爾參數(shù)更改元素的背景顏色

FeedbackBox.prototype.toggleError = function(obj, isError) {
  if(isError) {
    obj.css("background-color", "darkgrey");
  } else {
    obj.css("background-color", "");
  }
}

如您所見,它通過jQuery方法css設置background-color屬性。這是一個問題,因為我們希望通過樣式表規(guī)則指定它。

討厭的控制臺日誌

在開發(fā)小部件時,使用控制臺日誌來向開發(fā)人員提示當前正在執(zhí)行的內(nèi)容。在開發(fā)過程中這可能是一種不錯的方法,但在生產(chǎn)使用中肯定不是最好的方法。因此,我們需要找到一種方法來刪除所有這些調試語句。

攔截廣告服務器調用

該小部件很棒,但它有一個奇怪的行為。每次初始化腳本時,它都會向一個奇怪的廣告服務器發(fā)出請求,並在我們的頁面上顯示不必要的膨脹內(nèi)容。

FeedbackBox.prototype.init = function() {
  // 我們想要跳過的廣告服務器調用
  $.ajax('vendor/service.json', {
    method: 'GET'
  }).then(function(data) {
    console.log("FeedbackBox: AdServer contacted");
  });

  ...

注意:演示代碼針對Plunker中的JSON文件來模擬傳出的Ajax請求,但我希望您明白這一點。

覆蓋方法

MP的關鍵概念之一是獲取現(xiàn)有函數(shù)並使用自定義行為在調用原始代碼之前或之後對其進行增強。但調用原始實現(xiàn)並非總是必要的,因為有時您只想用自定義操作替換它。這種方法非常適合幫助我們解決硬編碼的背景顏色問題。

應用MP的位置必須在加載並提供原始實現(xiàn)之後。通常,您應該努力使更改盡可能接近目標,但請記住,目標的實現(xiàn)可能會隨著時間的推移而發(fā)生變化。至於我們的示例,初始化以及MP將進入文件main.js。

查看小部件實現(xiàn),我們可以看到有一個FeedbackBox對像作為小部件的根。稍後,將在其原型上實現(xiàn)toggleError函數(shù)。

FeedbackBox.prototype.toggleError = function(obj, isError) {
  if(isError) {
    obj.css("background-color", "darkgrey");
  } else {
    obj.css("background-color", "");
  }
}

由於JavaScript是一種動態(tài)語言,其對象可以在運行時修改,因此我們最終將做的只是用我們的自定義方法替換toggleError。唯一需要注意的是保持簽名(名稱和傳遞的參數(shù))相同。

FeedbackBox.prototype.init = function() {
  // 我們想要跳過的廣告服務器調用
  $.ajax('vendor/service.json', {
    method: 'GET'
  }).then(function(data) {
    console.log("FeedbackBox: AdServer contacted");
  });

  ...

新的實現(xiàn)現(xiàn)在只需向給定的元素添加一個錯誤類,從而允許我們通過css設置背景顏色。

增強方法

在前面的示例中,我們看到瞭如何通過提供我們自己的方法來覆蓋原始實現(xiàn)。另一方面,處理控制臺日誌應該只是過濾掉特定的調用並抑制它們。成功的關鍵是檢查您嵌入的代碼並嘗試理解其工作流程。通常,這是通過啟動您選擇的瀏覽器中的開發(fā)者控制臺並在加載的資源中窺視、添加斷點和調試目標代碼部分來完成的,以便了解它的功能。但是,這一次,您只需在另一個選項卡中打開名為vendor/jquery.feedBackBox.js的Plunker示例中的實現(xiàn)即可。

通過查看調試消息,我們可以看到它們中的每一個都以FeedbackBox:開頭。因此,實現(xiàn)我們想要的目標的一種簡單方法是攔截原始調用,檢查要寫入的提供的文本,並且僅當它不包含調試提示時才調用原始方法。

為此,讓我們首先將原始console.log存儲到一個變量中以供以後使用。然後,我們再次用我們的自定義實現(xiàn)覆蓋原始實現(xiàn),該實現(xiàn)首先檢查提供的屬性文本是否為字符串類型,如果是,則檢查它是否包含子字符串FeedbackBox:。如果是,我們將什麼也不做,否則我們將通過調用其apply方法來執(zhí)行原始控制臺代碼。

請注意,此方法將上下文作為第一個參數(shù),這意味著應該在該對像上調用該方法,以及一個神奇的arguments變量。後者是最初傳遞給原始console.log調用的所有參數(shù)的數(shù)組。

function FeedbackBox(elem, options) {
  this.options = options;  
  this.element = elem;  
  this.isOpen = false;
}

FeedbackBox.prototype.toggleError = function(obj, isError) {
  ...
}

注意:您可能想知道為什麼我們沒有簡單地轉發(fā)text屬性。好吧,console.log實際上可以用無限的參數(shù)調用,最終這些參數(shù)將連接到單個文本輸出。因此,與其定義所有這些參數(shù)(對於無限的可能性來說可能非常困難),我們只需轉發(fā)所有傳入的內(nèi)容。

攔截Ajax調用

最後但並非最不重要的一點是,讓我們看看如何解決廣告服務器問題。讓我們再次查看小部件的init函數(shù):

FeedbackBox.prototype.toggleError = function(obj, isError) {
  if(isError) {
    obj.css("background-color", "darkgrey");
  } else {
    obj.css("background-color", "");
  }
}

第一個想法可能是打開瀏覽器並蒐索如何覆蓋jQuery插件。根據(jù)您的搜索技能的好壞,您可能會或可能不會找到合適的答案。但是,讓我們停下來思考一下這裡到底發(fā)生了什麼。無論jQuery對其ajax方法做了什麼,它最終都會在某個時候創(chuàng)建一個本機XMLHttpRequest。

讓我們看看它在幕後是如何工作的。在MDN上找到的最簡單的示例向我們展示了這一點:

FeedbackBox.prototype.init = function() {
  // 我們想要跳過的廣告服務器調用
  $.ajax('vendor/service.json', {
    method: 'GET'
  }).then(function(data) {
    console.log("FeedbackBox: AdServer contacted");
  });

  ...

我們看到創(chuàng)建了一個新的XMLHttpRequest實例。它有一個onreadystatechange方法,我們實際上並不關心,然後是open和send方法。太好了。所以我們的想法是猴子補丁send方法並告訴它不要執(zhí)行對特定URL的調用。

function FeedbackBox(elem, options) {
  this.options = options;  
  this.element = elem;  
  this.isOpen = false;
}

FeedbackBox.prototype.toggleError = function(obj, isError) {
  ...
}

好吧,事實證明您無法從對象本身獲取目標URL。糟糕。那我們該怎麼辦?我們將其放在對像上。尋找獲取URL的第一個機會,我們可以看到open方法將其作為第二個參數(shù)接受。為了使URL在對象本身可用,讓我們首先MP open方法。

和以前一樣,我們將原始open方法存儲在一個變量中以供以後使用。然後我們用自定義實現(xiàn)覆蓋原始實現(xiàn)。由於我們可以使用JavaScript(一種動態(tài)語言),因此我們可以隨時創(chuàng)建一個新屬性並將其命名為_url,該屬性將設置為傳入?yún)?shù)的值。

FeedbackBox.prototype.toggleError = function(obj, isError) {
  if(isError) {
    obj.addClass("error");
  } else {
    obj.removeClass("error");
  }
};

除此之外,我們調用原始open方法,不做任何其他操作。

重新審視我們的send MP,現(xiàn)在很明顯如何解決條件檢查。以下是修改後的版本:

var originalConsoleLog = console.log;
console.log = function(text) {
  if (typeof text === "string" && text.indexOf("FeedbackBox:") === 0) {
    return;
  }

  originalConsoleLog.apply(console, arguments);
}

結論

我們在這裡看到的是關於使用猴子補丁在運行時更改代碼行為的簡短介紹。但更重要的是,我希望這篇文章能夠讓您了解如何處理猴子補丁問題。雖然補丁本身通常很簡單,但重要的是如何在運行時調整代碼的想法。

此外,我希望無論您對猴子補丁有何看法,您都有機會看到使用動態(tài)語言的美妙之處,它允許您動態(tài)地在運行時更改甚至本機實現(xiàn)。

關於實用猴子補丁的常見問題解答 (FAQ)

JavaScript中的猴子補丁的概念是什麼?

JavaScript中的猴子補丁是一種技術,其中內(nèi)置對像或用戶定義對象的行為被修改,通常是通過添加、修改或更改對象的原型來實現(xiàn)的。這是一種擴展或更改代碼行為而不更改原始源代碼的方法。此技術可用於實施修復、增強現(xiàn)有函數(shù),甚至用於測試和調試目的。

JavaScript和Python中的猴子補丁有何不同?

雖然JavaScript和Python中的猴子補丁的概念相同——修改或擴展對象的行為——但由於語言本身的差異,實現(xiàn)方式有所不同。在JavaScript中,猴子補丁通常是通過修改對象的原型來完成的,而在Python中,它是通過添加或更改類或實例方法來完成的。這兩種語言的靈活性都允許進行猴子補丁,但應謹慎使用此技術,以避免出現(xiàn)意外行為。

猴子補丁在JavaScript中被認為是一種好的實踐嗎?

猴子補丁是一個強大的工具,但它並非沒有爭議。雖然它可以快速修改或擴展功能而無需更改原始源代碼,但它也可能導致不可預測的行為和衝突,尤其是在過度使用或使用不當時。因此,通常建議謹慎和負責任地使用猴子補丁,並始終考慮對整個代碼庫的潛在影響。

猴子補丁的潛在風險是什麼?

猴子補丁的主要風險是它可能導致代碼中出現(xiàn)不可預測的行為和衝突。因為它修改了現(xiàn)有對象的行為,所以如果在代碼庫的其他地方使用了已修補的方法,它可能會破壞代碼。它還可能導致其他開發(fā)人員感到困惑,他們可能不知道這些修改。因此,務必清晰而全面地記錄任何猴子補丁。

如何在JavaScript中乾淨地猴子補丁一個函數(shù)?

要在JavaScript中乾淨地猴子補丁一個函數(shù),您可以圍繞原始函數(shù)創(chuàng)建一個包裝器。此包裝器函數(shù)將調用原始函數(shù),然後根據(jù)需要添加或修改行為。這樣,原始函數(shù)保持不變,附加行為清晰地分開,使代碼更易於理解和維護。

猴子補丁可以用於測試和調試嗎?

是的,猴子補丁可以作為測試和調試的有用工具。通過修改或擴展函數(shù)或方法的行為,您可以模擬不同的場景、注入錯誤或添加日誌來跟蹤代碼的執(zhí)行。但是,重要的是在生產(chǎn)代碼中刪除或隔離這些補丁,以避免任何意外的副作用。

原型在JavaScript中的猴子補丁中起什麼作用?

在JavaScript中,原型在猴子補丁中起著至關重要的作用。由於JavaScript是一種基於原型的語言,因此每個對像都有一個原型,它從中繼承屬性和方法。通過修改對象的原型,您可以更改該對象所有實例的行為。這是JavaScript中猴子補丁的基礎。

猴子補丁如何影響JavaScript中的性能?

猴子補丁對JavaScript性能的影響通常很小。但是,過度或不當使用猴子補丁可能會導致性能問題。例如,如果在代碼中頻繁使用已修補的方法,則附加行為可能會減慢執(zhí)行速度。因此,務必謹慎使用猴子補丁並定期監(jiān)控性能。

猴子補丁可以用來擴展內(nèi)置的JavaScript對象嗎?

是的,猴子補丁可以用來擴展內(nèi)置的JavaScript對象。通過修改內(nèi)置對象的原型,您可以添加新的方法或屬性,這些方法或屬性將可用於該對象的所有實例。但是,應謹慎執(zhí)行此操作,以避免與未來版本的JavaScript發(fā)生衝突,這些版本可能會引入相同的方法或屬性。

JavaScript中猴子補丁的一些替代方案是什麼?

JavaScript中猴子補丁有幾種替代方案。一種常見的方法是使用組合,您創(chuàng)建一個包含原始對象並添加或覆蓋行為的新對象。另一種方法是使用繼承,您創(chuàng)建一個從原始類繼承並覆蓋方法的新類。這些方法可以提供與猴子補丁類似的靈活性,但具有更好的封裝性和更少的衝突風險。

以上是JavaScript中猴子補丁的務實用途的詳細內(nèi)容。更多資訊請關注PHP中文網(wǎng)其他相關文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內(nèi)容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在JS中與日期和時間合作? 如何在JS中與日期和時間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時間處理需注意以下幾點:1.創(chuàng)建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區(qū)問題建議使用支持時區(qū)的庫,如Luxon。掌握這些要點能有效避免常見錯誤。

為什麼要將標籤放在的底部? 為什麼要將標籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數(shù)設為true實現(xiàn);2.事件冒泡是默認行為,useCapture設為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應用戶操作的時機和方式。

如何減少JavaScript應用程序的有效載荷大小? 如何減少JavaScript應用程序的有效載荷大??? Jun 26, 2025 am 12:54 AM

如果JavaScript應用加載慢、性能差,問題往往出在payload太大,解決方法包括:1.使用代碼拆分(CodeSplitting),通過React.lazy()或構建工具將大bundle拆分為多個小文件,按需加載以減少首次下載量;2.移除未使用的代碼(TreeShaking),利用ES6模塊機制清除“死代碼”,確保引入的庫支持該特性;3.壓縮和合併資源文件,啟用Gzip/Brotli和Terser壓縮JS,合理合併文件並優(yōu)化靜態(tài)資源;4.替換重型依賴,選用輕量級庫如day.js、fetch

JavaScript模塊上的確定JS綜述:ES模塊與COMPORJS JavaScript模塊上的確定JS綜述:ES模塊與COMPORJS Jul 02, 2025 am 01:28 AM

ES模塊和CommonJS的主要區(qū)別在於加載方式和使用場景。 1.CommonJS是同步加載,適用於Node.js服務器端環(huán)境;2.ES模塊是異步加載,適用於瀏覽器等網(wǎng)絡環(huán)境;3.語法上,ES模塊使用import/export,且必須位於頂層作用域,而CommonJS使用require/module.exports,可在運行時動態(tài)調用;4.CommonJS廣泛用於舊版Node.js及依賴它的庫如Express,ES模塊則適用於現(xiàn)代前端框架和Node.jsv14 ;5.雖然可混合使用,但容易引發(fā)問題

如何在node.js中提出HTTP請求? 如何在node.js中提出HTTP請求? Jul 13, 2025 am 02:18 AM

在Node.js中發(fā)起HTTP請求有三種常用方式:使用內(nèi)置模塊、axios和node-fetch。 1.使用內(nèi)置的http/https模塊無需依賴,適合基礎場景,但需手動處理數(shù)據(jù)拼接和錯誤監(jiān)聽,例如用https.get()獲取數(shù)據(jù)或通過.write()發(fā)送POST請求;2.axios是基於Promise的第三方庫,語法簡潔且功能強大,支持async/await、自動JSON轉換、攔截器等,推薦用於簡化異步請求操作;3.node-fetch提供類似瀏覽器fetch的風格,基於Promise且語法簡單

編寫清潔和可維護的JavaScript代碼的最佳實踐是什麼? 編寫清潔和可維護的JavaScript代碼的最佳實踐是什麼? Jun 23, 2025 am 12:35 AM

要寫出乾淨、可維護的JavaScript代碼,應遵循以下四點:1.使用清晰一致的命名規(guī)範,變量名用名詞如count,函數(shù)名用動詞開頭如fetchData(),類名用PascalCase如UserProfile;2.避免過長函數(shù)和副作用,每個函數(shù)只做一件事,如將更新用戶信息拆分為formatUser、saveUser和renderUser;3.合理使用模塊化和組件化,如在React中將頁面拆分為UserProfile、UserStats等小組件;4.寫註釋和文檔時點到為止,重點說明關鍵邏輯、算法選

var vs Let vs const:快速JS綜述解釋器 var vs Let vs const:快速JS綜述解釋器 Jul 02, 2025 am 01:18 AM

var、let和const的區(qū)別在於作用域、提升和重複聲明。 1.var是函數(shù)作用域,存在變量提升,允許重複聲明;2.let是塊級作用域,存在暫時性死區(qū),不允許重複聲明;3.const也是塊級作用域,必須立即賦值,不可重新賦值,但可修改引用類型的內(nèi)部值。優(yōu)先使用const,需改變變量時用let,避免使用var。

See all articles