現代JavaScript中的精美圖案:制冰廠

I’ve been working with JavaScript on and off since the late nineties. I didn’t really like it at first, but after the introduction of ES2015 (aka ES6), I began to appreciate JavaScript as an outstanding, dynamic programming language with enormous, expressive power.

從90年代末開始,我就一直在使用JavaScript。 一開始我并不真正喜歡它,但是在引入ES2015(又名ES6)之后,我開始欣賞JavaScript作為一種出色的動態編程語言,具有巨大的表達能力。

Over time, I’ve adopted several coding patterns that have lead to cleaner, more testable, more expressive code. Now, I am sharing these patterns with you.

隨著時間的流逝,我采用了幾種編碼模式,這些編碼模式導致了更簡潔,更可測試,更具表現力的代碼。 現在,我正在與您分享這些模式。

I wrote about the first pattern — “RORO” — in the article below. Don’t worry if you haven’t read it, you can read these in any order.

我在下面的文章中介紹了第一種模式-“ RORO”。 如果您還沒有閱讀,請不要擔心,您可以按任何順序閱讀它們。

Elegant patterns in modern JavaScript: ROROI wrote my first few lines of JavaScript not long after the language was invented. If you told me at the time that I…medium.freecodecamp.org

現代JavaScript中的優雅模式:RORO 在發明該語言后不久,我就編寫了前幾行JavaScript。 如果您當時告訴我我... medium.freecodecamp.org

Today, I’d like to introduce you to the “Ice Factory” pattern.

今天,我想向您介紹“制冰廠”模式。

An Ice Factory is just a function that creates and returns a frozen object. We’ll unpack that statement in a moment, but first let’s explore why this pattern is so powerful.

制冰廠只是一個創建和返回凍結對象的函數 。 稍后我們將解壓縮該語句,但首先讓我們探討一下為什么這種模式如此強大。

JavaScript類不是那么優雅 (JavaScript classes are not so classy)

It often makes sense to group related functions into a single object. For example, in an e-commerce app, we might have a cart object that exposes an addProduct function and a removeProduct function. We could then invoke these functions with cart.addProduct() and cart.removeProduct().

將相關功能分組到單個對象中通常很有意義。 例如,在一個電子商務應用程序中,我們可能有一個cart對象,該對象公開了addProduct函數和removeProduct函數。 然后,我們可以使用cart.addProduct()cart.removeProduct()調用這些函數。

If you come from a Class-centric, object oriented, programming language like Java or C#, this probably feels quite natural.

如果您來自以Java為中心的面向對象的,面向對象的編程語言(例如Java或C#),那可能會感覺很自然。

If you’re new to programming — now that you’ve seen a statement like cart.addProduct(). I suspect the idea of grouping together functions under a single object is looking pretty good.

如果您不cart.addProduct()編程,那么現在您已經看到了類似cart.addProduct()的語句。 我懷疑在單個對象下將功能分組在一起的想法看起來不錯。

So how would we create this nice little cart object? Your first instinct with modern JavaScript might be to use a class. Something like:

那么,我們將如何創建這個漂亮的小cart對象? 您對現代JavaScript的本能可能是使用class 。 就像是:

// ShoppingCart.js
export default class ShoppingCart {  constructor({db}) {    this.db = db  }    addProduct (product) {    this.db.push(product)  }    empty () {    this.db = []  }
get products () {    return Object      .freeze([...this.db])  }
removeProduct (id) {    // remove a product   }
// other methods
}
// someOtherModule.js
const db = [] const cart = new ShoppingCart({db})cart.addProduct({   name: 'foo',   price: 9.99})

Note: I’m using an Array for the db parameter for simplicity’s sake. In real code this would be something like a Model or Repo that interacts with an actual database.

注意 :為了簡單起見,我使用Array作為db參數。 在實際代碼中,這可能是與實際數據庫交互的模型或倉庫 。

Unfortunately — even though this looks nice — classes in JavaScript behave quite differently from what you might expect.

不幸的是,盡管看起來不錯,但是JavaScript中的類的行為與您期望的完全不同。

JavaScript Classes will bite you if you’re not careful.

如果您不小心,JavaScript類會咬您。

For example, objects created using the new keyword are mutable. So, you can actually re-assign a method:

例如,使用new關鍵字創建的對象是可變的。 因此,您實際上可以重新分配一個方法:

const db = []const cart = new ShoppingCart({db})
cart.addProduct = () => 'nope!' // No Error on the line above!
cart.addProduct({   name: 'foo',   price: 9.99}) // output: "nope!" FTW?

Even worse, objects created using the new keyword inherit the prototype of the class that was used to create them. So, changes to a class’ prototype affect all objects created from that class — even if a change is made after the object was created!

更糟糕的是,使用new關鍵字創建的對象將繼承用于創建它們的classprototype 。 因此,對類prototype更改會影響從class創建的所有對象-即使在創建對象之后進行了更改!

Look at this:

看這個:

const cart = new ShoppingCart({db: []})const other = new ShoppingCart({db: []})
ShoppingCart.prototype  .addProduct = () => ‘nope!’// No Error on the line above!
cart.addProduct({   name: 'foo',   price: 9.99}) // output: "nope!"
other.addProduct({   name: 'bar',   price: 8.88}) // output: "nope!"

Then there's the fact that this In JavaScript is dynamically bound. So, if we pass around the methods of our cart object, we can lose the reference to this. That’s very counter-intuitive and it can get us into a lot of trouble.

然后事實是, this In JavaScript是動態綁定的。 因此,如果我們傳遞cart對象的方法,則可能會丟失this的引用。 這是違反直覺的,并且可能使我們陷入很多麻煩。

A common trap is assigning an instance method to an event handler.

一個常見的陷阱是將實例方法分配給事件處理程序。

Consider our cart.empty method.

考慮我們的cart.empty方法。

empty () {    this.db = []  }

If we assign this method directly to the click event of a button on our web page…

如果我們直接將此方法分配給網頁上按鈕的click事件,則……

<button id="empty">  Empty cart</button>
---
document  .querySelector('#empty')  .addEventListener(    'click',     cart.empty  )

… when users click the empty button, their cart will remain full.

…當用戶單擊空button ,他們的cart將保持滿滿。

It fails silently because this will now refer to the button instead of the cart. So, our cart.empty method ends up assigning a new property to our button called db and setting that property to [] instead of affecting the cart object’s db.

它會靜默失敗,因為this現在將引用button而不是cart 。 因此,我們的cart.empty方法最終為button db分配了一個新屬性,并將該屬性設置為[]而不影響cart對象的db

This is the kind of bug that will drive you crazy because there is no error in the console and your common sense will tell you that it should work, but it doesn’t.

這種錯誤會使您發瘋,因為控制臺中沒有錯誤,并且您的常識將告訴您它應該起作用,但事實并非如此。

To make it work we have to do:

為了使其工作,我們必須做:

document  .querySelector("#empty")  .addEventListener(    "click",     () => cart.empty()  )

Or:

要么:

document  .querySelector("#empty")  .addEventListener(    "click",     cart.empty.bind(cart)  )

I think Mattias Petter Johansson said it best:

我認為Mattias Petter Johansson 說得最好 :

new and this [in JavaScript] are some kind of unintuitive, weird, cloud rainbow trap.”

newthis [在JavaScript]是某種直觀的,怪異的,云彩虹陷阱。”

制冰廠營救 (Ice Factory to the rescue)

As I said earlier, an Ice Factory is just a function that creates and returns a frozen object. With an Ice Factory our shopping cart example looks like this:

如前所述, Ice Factory只是一個創建并返回凍結對象的函數 。 對于制冰廠,我們的購物車示例如下所示:

// makeShoppingCart.js
export default function makeShoppingCart({  db}) {  return Object.freeze({    addProduct,    empty,    getProducts,    removeProduct,    // others  })
function addProduct (product) {    db.push(product)  }    function empty () {    db = []  }
function getProducts () {    return Object      .freeze([...db])  }
function removeProduct (id) {    // remove a product  }
// other functions}
// someOtherModule.js
const db = []const cart = makeShoppingCart({ db })cart.addProduct({   name: 'foo',   price: 9.99})

Notice our “weird, cloud rainbow traps” are gone:

注意我們的“奇怪的云彩虹陷阱”已經消失了:

  • We no longer need new.

    我們不再需要new

    We just invoke a plain old JavaScript function to create our

    我們只是調用一個普通的舊JavaScript函數來創建我們的

    cart object.

    cart對象。

  • We no longer need this.

    我們不再需要this

    We can access the

    我們可以訪問

    db object directly from our member functions.

    db對象直接來自我們的成員函數。

  • Our cart object is completely immutable.

    我們的cart對象是完全不變的。

    Our cart object is completely immutable. Object.freeze() freezes the cart object so that new properties can’t be added to it, existing properties can’t be removed or changed, and the prototype can’t be changed either. Just remember that Object.freeze() is shallow, so if the object we return contains an array or another object we must make sure to Object.freeze() them as well. Also, if you’re using a frozen object outside of an ES Module, you need to be in strict mode to make sure that re-assignments cause an error rather than just failing silently.

    我們的cart對象是完全不變的。 Object.freeze()凍結cart對象,以便不能向其添加新屬性,也不能刪除或更改現有屬性,也不能更改原型。 只要記住Object.freeze()淺層的 ,所以如果我們返回的對象包含一個array或另一個object我們必須確保也將它們對Object.freeze() 。 另外,如果您使用的是ES Module之外的凍結對象,則需要處于嚴格模式下 ,以確保重新分配會導致錯誤,而不僅僅是靜默失敗。

請注意一點隱私 (A little privacy please)

Another advantage of Ice Factories is that they can have private members. For example:

冰工廠的另一個優勢是他們可以擁有私人成員。 例如:

function makeThing(spec) {  const secret = 'shhh!'
return Object.freeze({    doStuff  })
function doStuff () {    // We can use both spec    // and secret in here   }}
// secret is not accessible out here
const thing = makeThing()thing.secret // undefined

This is made possible because of Closures in JavaScript, which you can read more about on MDN.

由于JavaScript中的Closures,使之成為可能,您可以在MDN上了解更多信息。

請一點感謝 (A little acknowledgement please)

Although Factory Functions have been around JavaScript forever, the Ice Factory pattern was heavily inspired by some code that Douglas Crockford showed in this video.

盡管Factory Functions永遠都圍繞著JavaScript進行,但是Ice Factory模式在很大程度上受到了Douglas Crockford在此視頻中顯示的一些代碼的啟發。

Here’s Crockford demonstrating object creation with a function he calls “constructor”:

這是克羅克福德(Crockford)展示的對象創建過程,他稱之為“構造函數”:

My Ice Factory version of the Crockford example above would look like this:

上面的Crockford示例的Ice Factory版本如下所示:

function makeSomething({ member }) {  const { other } = makeSomethingElse()     return Object.freeze({     other,    method  })
function method () {    // code that uses "member"  }}

I took advantage of function hoisting to put my return statement near the top, so that readers would have a nice little summary of what’s going on before diving into the details.

我利用函數提升將我的return語句放在頂部附近,以便讀者在深入了解細節之前可以對所發生的事情有一個很好的總結。

I also used destructuring on the spec parameter. And I renamed the pattern to “Ice Factory” so that it’s more memorable and less easily confused with the constructor function from a JavaScript class. But it’s basically the same thing.

我還對spec參數使用了解構。 然后,我將模式重命名為“ Ice Factory”,以使其更令人難忘,并且不易與JavaScript classconstructor函數混淆。 但這基本上是同一回事。

So, credit where credit is due, thank you Mr. Crockford.

所以,只要有信用就可以信用,謝謝克羅克福德先生。

Note: It’s probably worth mentioning that Crockford considers function “hoisting” a “bad part” of JavaScript and would likely consider my version heresy. I discussed my feelings on this in a previous article and more specifically, this comment.

注意: 可能值得一提的是Crockford將函數“提升”為JavaScript的“不良部分”,并可能將我的版本視為異端。 我在上一篇文章中 ,特別是在評論中 ,討論了對此的感受。

那繼承呢? (What about inheritance?)

If we tick along building out our little e-commerce app, we might soon realize that the concept of adding and removing products keeps cropping up again and again all over the place.

如果我們逐步構建自己的小型電子商務應用程序,我們可能很快就會意識到添加和刪除產品的概念不斷在整個地方反復出現。

Along with our Shopping Cart, we probably have a Catalog object and an Order object. And all of these probably expose some version of `addProduct` and `removeProduct`.

除了購物車,我們可能還有一個Catalog對象和一個Order對象。 所有這些可能都暴露了`addProduct`和`removeProduct`的某些版本。

We know that duplication is bad, so we’ll eventually be tempted to create something like a Product List object that our cart, catalog, and order can all inherit from.

我們知道復制是不好的,所以我們最終會被誘惑創建類似產品清單對象的東西,而我們的購物車,目錄和訂單都可以從中繼承。

But rather than extending our objects by inheriting a Product List, we can instead adopt the timeless principle offered in one of the most influential programming books ever written:

但是,除了繼承繼承產品列表來擴展對象之外,我們還可以采用有史以來最有影響力的編程書籍之一中提供的永恒原理:

“Favor object composition over class inheritance.”

“在類繼承上的主要對象組成。”

In fact, the authors of that book — colloquially known as “The Gang of Four” — go on to say:

實際上,這本書的作者(俗稱“四人幫”)繼續說:

“…our experience is that designers overuse inheritance as a reuse technique, and designs are often made more reusable (and simpler) by depending more on object composition.”
“……我們的經驗是,設計師將繼承作為一種重用技術而過度使用,并且通過更多地依賴于對象的組成,設計通常變得更可重用(和更簡單)。”

So, here’s our product list:

因此,這是我們的產品列表:

function makeProductList({ productDb }) {  return Object.freeze({    addProduct,    empty,    getProducts,    removeProduct,    // others  )}   // definitions for   // addProduct, etc…}

And here’s our shopping cart:

這是我們的購物車:

function makeShoppingCart(productList) {  return Object.freeze({    items: productList,    someCartSpecificMethod,    // …)}
function someCartSpecificMethod () {  // code   }}

And now we can just inject our Product List into our Shopping Cart, like this:

現在,我們可以將產品列表插入購物車中,如下所示:

const productDb = []const productList = makeProductList({ productDb })
const cart = makeShoppingCart(productList)

And use the Product List via the `items` property. Like:

并通過“ items”屬性使用“產品列表”。 喜歡:

cart.items.addProduct()

It may be tempting to subsume the entire Product List by incorporating its methods directly into the shopping cart object, like so:

通過將其方法直接合并到購物車對象中,可能會試圖包含整個產品列表,如下所示:

function makeShoppingCart({   addProduct,  empty,  getProducts,  removeProduct,  …others}) {  return Object.freeze({    addProduct,    empty,    getProducts,    removeProduct,    someOtherMethod,    …others)}
function someOtherMethod () {  // code   }}

In fact, in an earlier version of this article, I did just that. But then it was pointed out to me that this is a bit dangerous (as explained here). So, we’re better off sticking with proper object composition.

實際上,在本文的早期版本中,我只是這樣做的。 但后來有人向我指出,這是一個有點危險(如解釋在這里 )。 因此,我們最好堅持適當的對象組成。

Awesome. I’m Sold!

太棒了 我賣了!

Whenever we’re learning something new, especially something as complex as software architecture and design, we tend to want hard and fast rules. We want to hear thing like “always do this” and “ never do that.”

每當我們學習新的東西,尤其是像軟件體系結構和設計這樣復雜的東西時,我們都傾向于要求嚴格而快速的規則。 我們希望聽到“ 永遠做”和“ 永遠不做”的事情。

The longer I spend working with this stuff, the more I realize that there’s no such thing as always and never. It’s about choices and trade-offs.

我花在這個東西上的時間越長,我越意識到沒有永遠存在的東西 這與選擇和權衡有關。

Making objects with an Ice Factory is slower and takes up more memory than using a class.

與使用類相比,使用Ice Factory制作對象要慢,并且占用更多內存。

In the types of use case I’ve described, this won’t matter. Even though they are slower than classes, Ice Factories are still quite fast.

在我所描述的用例類型中,這無關緊要。 盡管它們比課堂要慢,但是冰工廠仍然相當快。

If you find yourself needing to create hundreds of thousands of objects in one shot, or if you’re in a situation where memory and processing power is at an extreme premium you might need a class instead.

如果您發現自己需要一次創建數十萬個對象,或者您的內存和處理能力極其昂貴,則可能需要一個類。

Just remember, profile your app first and don’t prematurely optimize. Most of the time, object creation is not going to be the bottleneck.

請記住,請先配置您的應用程序,然后過早進行優化。 大多數情況下,對象創建不會成為瓶頸。

Despite my earlier rant, Classes are not always terrible. You shouldn’t throw out a framework or library just because it uses classes. In fact, Dan Abramov wrote pretty eloquently about this in his article, How to use Classes and Sleep at Night.

盡管我以前很吵,但上課并不總是那么糟糕。 您不應該僅僅因為框架或庫使用了類就扔掉它。 實際上, 丹·阿布拉莫夫 ( Dan Abramov )在他的文章“ 如何使用班級和夜間睡眠”中雄辯地寫道。

Finally, I need to acknowledge that I’ve made a bunch of opinionated style choices in the code samples I’ve presented to you:

最后,我需要承認,在提供給您的代碼示例中,我已經做出了許多自以為是的樣式選擇:

  • I use function statements instead of function expressions.

    我使用函數語句代替函數表達式 。

  • I put my return statement near the top (this is made possible by my use of function statements, see above).

    我將return語句放在頂部附近(這可以通過使用函數語句來實現,請參見上文)。
  • I name my factory function, makeX instead of createX or buildX or something else.

    我將工廠函數makeXmakeX而不是createXbuildX或其他名稱。

  • My factory function takes a single, destructured, parameter object.

    我的工廠函數采用了一個經過分解的單個參數對象 。

  • I don’t use semi-colons (Crockford would also NOT approve of that)

    我不使用分號( Crockford也不會贊成 )

  • and so on…

    等等…

You may make different style choices, and that’s okay! The style is not the pattern.

您可以選擇不同的樣式, 這沒關系 ! 樣式不是樣式。

The Ice Factory pattern is just: use a function to create and return a frozen object. Exactly how you write that function is up to you.

Ice Factory模式就是: 使用函數創建并返回凍結的對象 。 具體如何編寫該函數取決于您。

If you’ve found this article useful, please smash that applause icon a bunch of times to help spread the word. And if you want to learn more stuff like this, please sign up for my Dev Mastery newsletter below. Thanks!

如果您發現這篇文章很有用,請搗毀該掌聲圖標多次,以幫助您宣傳。 如果您想了解更多類似的內容,請在下面注冊我的開發精通通訊。 謝謝!

2019年更新:這是我經常使用此模式的視頻! (UPDATE 2019: Here’s a video where I use this pattern, a lot!)

翻譯自: https://www.freecodecamp.org/news/elegant-patterns-in-modern-javascript-ice-factory-4161859a0eee/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394522.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394522.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394522.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

惠普omen測試軟件,雙GTX1080奢華魔方PC 惠普OMEN X評測

惠普最近一段時間在游戲PC領域著力發力&#xff0c;桌面的暗影精靈家族熱賣&#xff0c;如火如荼的勢頭終于傳導到了臺式機領域。而今&#xff0c;惠普也終于有了自己正統意義上的重型武器——桌面游戲臺式機OMEN 900暗影精靈II 系列。今天我們就要為大家評測這款三萬元的臺式機…

python 清華鏡像_Anaconda3清華鏡像 V5.3.1 最新免費版

相關軟件軟件大小版本說明下載地址Anaconda3清華鏡像是一款功能強大的python管理工具&#xff0c;此軟件集成了Conda和Python等大量科學計算分析的包&#xff0c;可以幫助用戶快速實現項目環境的配置&#xff0c;有需要的趕快來試試吧&#xff01;【功能特點】1、省時省心&…

Qt第五課 無構造函數可以接受源類型,或構造函數重載決策不明確

場景QJsonArray rgParams { 10, 20, 30, 40 };編譯代碼的時候出錯&#xff0c;C11標準才支持這種類的初始化列表語法&#xff0c;因此如果當前VS的版本過低&#xff0c;必須調整已有的代碼&#xff0c;例子如下&#xff1a;QJsonArray rgParams;rgParams.insert(0, 10);rgPar…

二. linux基礎命令

linux的基本命令一般有100多個&#xff0c;多練就可以了&#xff1b; 如果登陸用戶是root&#xff0c;那么是#&#xff1b;如果是其他用戶&#xff0c;則顯示的是$ 練習&#xff1a;基本命令 1.創建一個目錄/data mkdir /data ls -ld /data 2.在/data下面創建一個文件oldboy.tx…

mac 沒有所有開發者_為什么開發人員應該像產品所有者那樣思考

mac 沒有所有開發者by Sajal Sarwar Sharma通過薩加爾薩瓦夏爾馬 為什么開發人員應該像產品所有者那樣思考 (Why developers should think more like product owners) You have just deployed your long-awaited feature to production after a long and gruesome month of co…

程序員這樣對待簡歷,你期望面試官怎么對待你?

為什么想到談這個問題呢&#xff1f; 前段時間公司因業務擴展需要招聘幾個研發、運維以及測試人員&#xff0c;在看面試者的簡歷時&#xff0c;發現很多人都沒有認真的去對待簡歷&#xff0c;只是把招聘網站上的打印一下就好了&#xff01; 這就讓我想問幾個問題&#xff1a; 1…

mfc try catch 捕獲并顯示_“全棧2019”Java異常第十七章:Error該不該被捕獲?

難度初級學習時間30分鐘適合人群零基礎開發語言Java開發環境JDK v11IntelliJ IDEA v2018.3友情提示本教學屬于系列教學&#xff0c;內容具有連貫性&#xff0c;本章使用到的內容之前教學中都有詳細講解。本章內容針對零基礎或基礎較差的同學比較友好&#xff0c;可能對于有基礎…

長春高中計算機考試時間安排,長春部分高中期末考試時間出爐!

原標題&#xff1a;長春部分高中期末考試時間出爐&#xff01;上次跟大家分享了中小學的放假時間&#xff0c;今天就來說說期末考試時間吧&#xff01;雖然有的學校時間未定&#xff0c;但是按照慣例&#xff0c;長春市各大高中高一高二年級&#xff0c;本次的期末考試時間&…

用習慣了windows系統要怎樣去認識linux系統(一)

一、前言對于普通用戶來說99%都使用的是windows操作系統&#xff0c;即便那些會使用linux系統的技術員來說&#xff0c;他們PC上安裝的也是windows系統。linux系統只是用于服務器市場&#xff0c;可以說現在服務器市場80%使用的是linux系統。那它們兩系統之間有哪些區別呢&…

spring 配置文件模板

<?xml version"1.0" encoding"UTF-8"?><beans xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc"http://www.springframework.org/schema/mvc" xmlns:context"http://www.springframework.org/schema…

VAssistX使用小竅門

日常使用中的一些VAssistX使用小竅門&#xff0c;簡單總結下 一&#xff0c;修改VAssistX默認緩存文件路徑&#xff0c;防止默認C盤被占用空間過大 1、 打開注冊表HKCU\Software\Whole Tomato&#xff0c;新建UserDataDir&#xff0c;數值為要修改的路徑&#xff0c;如下圖&am…

react 交互_如何在React應用程序中跟蹤用戶交互

react 交互by Faouzi Oudouh通過Faouzi Oudouh 如何在React應用程序中跟蹤用戶交互 (How to track user interactions in your React app) Worry not about which Analytics provider you need to gather user interaction within your app.不必擔心需要哪個Analytics(分析)提…

shell python比較_shell中的條件判斷以及與python中的對比

shell中比如比較字符串、判斷文件是否存在及是否可讀等&#xff0c;通常用"[]"來表示條件測試。注意&#xff1a;這里的空格很重要。要確保方括號的空格。if ....; then python中的條件判斷&#xff1a; if ....: (此處是冒號&#xff0c;不同…

服務器麒麟系統能設置mtu嗎,麒麟操作系統安裝標準手冊-20210405220006.docx-原創力文檔...

精品文檔精品文檔PAGEPAGE47精品文檔PAGE.銀河麒麟V3操作系統安裝手冊V1.2編制&#xff1a;王帥校核&#xff1a;朱本亮審定&#xff1a;周俊...文檔更新日志&#xff1a;序號修訂時間修訂內容修改人審定人012017-04-12發布文檔V1.0王帥周俊022017-05-11增加啟動安裝時藍屏錯誤…

多個 gradle 文件夾 \.gradle\wrapper\dists\ 設置gradle不是每次都下載

韓夢飛沙 韓亞飛 313134555qq.com yue31313 han_meng_fei_sha 設置gradle不是每次都下載 \.gradle\wrapper\dists\ 在你導入項目的時候&#xff0c;有個選項的&#xff1a; 你要是選了Use default gradle mapper就會下載一次&#xff0c;Use local gradle distribution就會…

docker使用方式

docker使用方式安裝&#xff1a;1.安裝依賴 yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 2添加yum源 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo 3.安裝 yum install docker-ce docker-ce-cli contain…

使用AxiosJavaScript中的簡單HTTP請求

Interested in learning JavaScript? Get my ebook at jshandbook.com有興趣學習JavaScript嗎&#xff1f; 在jshandbook.com上獲取我的電子書 介紹 (Introduction) Axios is a very popular JavaScript library you can use to perform HTTP requests. It works in both Brow…

Linux中通過命令直接刪除文件中最后一行

何謂Sed(Stream EDitor):Sed原為UNIX系統上的非交談式文字編輯器(non-interactive stream editor)。當Sed讀入待編輯文件&#xff0c;會依編輯命令來進行文件的編輯工作。sed -i $d file如同其它UNIX的指令一般&#xff0c;Sed亦是由標準輸入(standard input)讀入欲編輯的文件&…

vb獲取數組長度_如何實現數組的二分查找

二分查找是一種極其高效、簡練的查找算法&#xff0c;它不僅簡單&#xff0c;易用&#xff0c;而且還非常的高效。相對于順序查找&#xff0c;二分查找在效率是呈現指數性提升&#xff0c;數據量越大&#xff0c;越能體現出二分查找法的優勢。二分查找的查找過程是&#xff1a;…

400錯誤返回了服務器信息,使用Spring MVC,接受JSON錯誤的POST請求會導致返回默認的400錯誤代碼服務器頁面...

我正在使用RESTAPI。接收到帶有錯誤JSON的POST消息(例如{sdfasdfasdf})會使Spring返回默認服務器頁面&#xff0c;以顯示400錯誤請求錯誤。我不想返回頁面&#xff0c;我想返回自定義JSON錯誤對象。當使用ExceptionHandler引發異常時&#xff0c;可以執行此操作。因此&#xff…