现代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.mzph.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…