重拾信心!通過建造者模式可以解決的4大JavaScript問題

2020-12-06 讀芯術

全文共11238字,預計學習時長33分鐘

圖源:Pexels

在用JavaScript開發APP時,你可能會覺得創建一個複雜對象很困難。一旦這關係到代碼中的某個細節,創建複雜對象就會變得更加複雜,因為它會使APP很佔內存。

這樣的困難一般有很多形式。一種是,在試圖創建不同種類的複雜對象時,代碼會變得很冗長;另一種,創建不同對象的過程會被拉長,因為同一等級模塊中的邏輯需要梳理清晰。

這個時候,我們就需要運用到建造者模式(builderpattern)。一些問題運用建造者模式可以得到輕鬆改善。

首先,什麼是建造者模式(builder pattern)?

建造者模式可以將一個複雜的對象的構建與其表示相分離,使得同樣的構建過程可以創建不同的表示。也就是說如果我們用了建造者模式,那麼用戶就需要指定需要建造的類型就可以得到它們,而具體建造的過程和細節就不需要知道了。建造者模式實際就是一個指揮者,一個建造者,一個使用指揮者調用具體建造者工作得出結果的客戶。

建造者模式主要用於「分步驟構建一個複雜的對象」,在這其中「分步驟」是一個穩定的算法,而複雜對象的各個部分則經常變化。

通俗的說:就是一個白富美需要建一個別墅,然後直接找包工頭,包工頭再找工人把別墅建好。這其中白富美不用直接一個一個工人的去找。而且包工頭知道白富美的需求,知道哪裡可以找到工人,工人可以幹活,中間節省了白富美的和工人之間溝通的成本,白富美也不需要知道房子具體怎麼建,最後能拿到房就可以了。

圖源:Pexels

今天的文章裡,小芯就將和大家一起討論文章開頭提及的問題,以及如何在使用JavaScript的設計過程中解決這些問題。哪些問題可以通過建造者模式得到輕鬆改善?

首先來看一個不使用建造者模式的例子,再和使用建造者模式的例子進行對比,我們可以看到代碼上的區別。

在下面的代碼示例中,我們試圖定義「frog(青蛙)」這一類。假設,為了讓青蛙完全有能力在野外生存,它們需要兩隻眼睛、四條腿、嗅覺、味覺和心跳。

現在,很明顯,在現實世界中,有更多事情牽涉其中,需要某一種氣味才能生存聽起來很荒謬,但我們不需要對每件事都完全實事求是,只要讓它既簡單又有趣就行了。

不用建造者模式

classFrog {

constructor(name, gender, eyes, legs, scent, tongue, heart, weight, height) {

this.name= name

this.gender = gender

this.eyes = eyes

this.legs = legs

this.scent = scent

this.tongue = tongue

this.heart = heart

if (weight) {

this.weight = weight

}

if (height) {

this.height= height

}

}

}

Frog.js hosted with by GitHub

使用建造者模式

classFrogBuilder {

constructor(name, gender) {

this.name= name

this.gender = gender

}

setEyes(eyes) {

this.eyes = eyes

returnthis

}

setLegs(legs) {

this.legs = legs

returnthis

}

setScent(scent) {

this.scent = scent

returnthis

}

setTongue(tongue) {

this.tongue = tongue

returnthis

}

setHeart(heart) {

this.heart = heart

returnthis

}

setWeight(weight) {

this.weight = weight

returnthis

}

setHeight(height) {

this.height= height

returnthis

}

}

FrogBuilder.js hosted with by GitHub

現在這看起來好像有點矯枉過正了,因為建造者模式下的代碼量更大。

但是如果深入挖掘在開發過程可能發生的所有情況,您將發現,對比這兩個示例,建造者模式下的代碼示例將在促進簡單性、可維護性和提供更多機會,從而在實現強大功能的方面更佔優勢。

下面四個是在JavaScript中利用建造者模式設計就可以輕鬆解決的大問題。

一、可讀性

圖源:Pexels

最近的代碼示例已經變得有點難以閱讀,因為我們必須同時處理多種變化。

如果想創造「青蛙」的實例,就沒有辦法對其置之不理,只能去理解整個過程。

此外,提供一些文檔,否則不能理解為什麼tongueWidth被重命名為width。這太荒謬了!

classFrogBuilder {

constructor(name, gender) {

// Ensure that the first character is always capitalized

this.name= name.charAt(0).toUpperCase() + name.slice(1)

this.gender = gender

}

formatEyesCorrectly(eyes) {

returnArray.isArray(eyes) ? { left: eye[0], right: eye[1] } : eyes

}

setEyes(eyes) {

this.eyes =this.formatEyes(eyes)

returnthis

}

setLegs(legs) {

if (!Array.isArray(legs)) {

thrownewError('"legs" is not an array')

}

this.legs = legs

returnthis

}

setScent(scent) {

this.scent = scent

returnthis

}

updateTongueWidthFieldName(tongue) {

constnewTongue= { ...tongue }

delete newTongue['tongueWidth']

newTongue.width= tongue.width

return newTongue

}

setTongue(tongue) {

constisOld='tongueWidth'in tongue

this.tongue = isOld

?this.updateTongueWidthFieldName(tongue, tongue.tongueWidth)

: tongue

returnthis

}

setHeart(heart) {

this.heart = heart

returnthis

}

setWeight(weight) {

if (typeof weight !=='undefined') {

this.weight = weight

}

returnthis

}

setHeight(height) {

if (typeof height !=='undefined') {

this.height= height

}

returnthis

}

build() {

returnnewFrog(

this.name,

this.gender,

this.eyes,

this.legs,

this.scent,

this.tongue,

this.heart,

this.weight,

this.height,

)

}

}

constlarry=newFrogBuilder('larry', 'male')

.setEyes([{ volume:1.1 }, { volume:1.12 }])

.setScent('sweaty socks')

.setHeart({ rate:22 })

.setWeight(6)

.setHeight(3.5)

.setLegs([

{ size:'small' },

{ size:'small' },

{ size:'small' },

{ size:'small' },

])

.setTongue({ tongueWidth:18, color:'dark red', type:'round' })

.build()

FrogBuilder.js hosted with by GitHub

從以下四個方面來獲得提升代碼可讀性的能力:

1. 使方法的名稱具有充分的自記錄性

對我們來說,updateTongueWidthFieldName的用處和使用原因很容易被定義。

我們知道這是正在更新欄位名。我們也知道其中的原因,因為update這個詞已經意味著更新!這個自記錄的代碼幫助我們假設一個舊的欄位名,需要更改以使用新的。

2. 簡短的構造器

完全可以以後再設置別的屬性!

3. 當啟動一個新「frog」時,要清楚了解每個參數

就像讀英語一樣,你需要清楚地設置出「眼睛」「腿」,然後使用建造方法去構建「青蛙」。

4. 將每個邏輯隔離在單獨的容易執行的代碼塊中

當你修改一些東西時,只需要專注於一件事,那就是在代碼塊中被隔離出來的東西。

二、樣板文件(通過模板化解決)

圖源:Unsplash

我們將來可能會遇到的一個問題是,最後會得到一些重複的代碼。

例如,回顧「frog」實例時,你認為當我們想要創造某些特殊類型的青蛙時,它們會具有完全相同的特性嗎?

在現實世界中,青蛙有不同的變種。例如,蟾蜍是青蛙的一種,但並非所有的青蛙都是蟾蜍。所以,這告訴我們蟾蜍有一些與普通青蛙不同的特性。

蟾蜍和青蛙的一個區別是,蟾蜍的大部分時間是在陸地上度過的,而普通青蛙是在水裡。此外,蟾蜍的皮膚有幹疙瘩,而正常青蛙的皮膚有點黏。

這意味著我們必須以某種方式確保每次青蛙被實例化時,只有一些值可以通過,也有一些值必須通過。

讓我們回到Frog構造器,添加兩個新參數:棲息地和皮膚:

將來可能會遇到的一個問題是,最終會得到一些重複的代碼。

classFrog {

constructor(

name,

gender,

eyes,

legs,

scent,

tongue,

heart,

habitat,

skin,

weight,

height,

) {

this.name= name

this.gender = gender

this.eyes = eyes

this.legs = legs

this.scent = scent

this.tongue = tongue

this.heart = heart

this.habitat = habitat

this.skin = skin

if (weight) {

this.weight = weight

}

if (height) {

this.height= height

}

}

}

Frog.js hosted with by GitHub

在兩次簡單的更改後,這個構造器已經有點混亂了!這就是為什麼推薦使用建造者模式。

如果把棲息地和皮膚參數放在最後,可能會出現錯誤,因為體重和身高可能很難確定,而這些又都是可變的!

又由於這種可選性,如果用戶不傳遞這些信息,就會出現錯誤的棲息地和皮膚信息。

編輯FrogBuilder來支持棲息地和皮膚:

setHabitat(habitat) {

this.habitat = habitat

}

setSkin(skin) {

this.skin = skin

}

FrogBuilder.js hosted with by GitHub

現在假設需要兩隻分開的蟾蜍和一隻正常的青蛙:

// frog

constsally=newFrogBuilder('sally', 'female')

.setEyes([{ volume:1.1 }, { volume:1.12 }])

.setScent('blueberry')

.setHeart({ rate:12 })

.setWeight(5)

.setHeight(3.1)

.setLegs([

{ size:'small' },

{ size:'small' },

{ size:'small' },

{ size:'small' },

])

.setTongue({ width:12, color:'navy blue', type:'round' })

.setHabitat('water')

.setSkin('oily')

.build()

// toad

constkelly=newFrogBuilder('kelly', 'female')

.setEyes([{ volume:1.1 }, { volume:1.12 }])

.setScent('black ice')

.setHeart({ rate:11 })

.setWeight(5)

.setHeight(3.1)

.setLegs([

{ size:'small' },

{ size:'small' },

{ size:'small' },

{ size:'small' },

])

.setTongue({ width:12.5, color:'olive', type:'round' })

.setHabitat('land')

.setSkin('dry')

.build()

// toad

constmike=newFrogBuilder('mike', 'male')

.setEyes([{ volume:1.1 }, { volume:1.12 }])

.setScent('smelly socks')

.setHeart({ rate:15 })

.setWeight(12)

.setHeight(5.2)

.setLegs([

{ size:'medium' },

{ size:'medium' },

{ size:'medium' },

{ size:'medium' },

])

.setTongue({ width:12.5, color:'olive', type:'round' })

.setHabitat('land')

.setSkin('dry')

.build()

FrogBuilder.js hosted with by GitHub

那麼,這裡的代碼哪裡重複了呢?

如果仔細觀察,就會注意到我們必須重複蟾蜍的棲息地和皮膚設置。如果再有五個只屬於蟾蜍的設置呢?那麼每次輸出蟾蜍或者是普通青蛙的時候,都要手動操作這個模板。

創建一個模板,按照慣例,通常稱之為指導器(director)。

指導器負責執行創建對象的步驟——通常是在構建最終對象時可以預先定義一些公共結構,比如本例中的蟾蜍。

因此,不必手動設置蟾蜍之間的不同屬性,可以讓指導器直接生成:

classToadBuilder {

constructor(frogBuilder) {

this.builder = frogBuilder

}

createToad() {

returnthis.builder.setHabitat('land').setSkin('dry')

}

}

let mike =newFrogBuilder('mike', 'male')

mike =newToadBuilder(mike)

.setEyes([{ volume:1.1 }, { volume:1.12 }])

.setScent('smelly socks')

.setHeart({ rate:15 })

.setWeight(12)

.setHeight(5.2)

.setLegs([

{ size:'medium' },

{ size:'medium' },

{ size:'medium' },

{ size:'medium' },

])

.setTongue({ width:12.5, color:'olive', type:'round' })

.build()

ToadBuilder.js hosted with by GitHub

這樣,就可以避免將蟾蜍的共享樣板文件應用到所有,而只關注其所需屬性。當蟾蜍有更多的獨有屬性時,這將變得更加有用。

三、代碼混亂

圖源:Unsplash

由於粗心大意地開發大型功能代碼塊而導致的錯誤和事故並不少見。此外,當一個代碼塊需要處理太多事情時,指令就很容易被搞錯。

那麼,當功能代碼塊(比如構造器)中有太多待處理時,會遇到什麼情況?

回到第一個代碼示例(在不用建造者模式的情況下實現),假設必須先添加一些額外的邏輯來接受傳入的參數,然後才能將它們應用於實例:

classFrog {

constructor(name, gender, eyes, legs, scent, tongue, heart, weight, height) {

if (!Array.isArray(legs)) {

thrownewError('Parameter "legs" is not an array')

}

// Ensure that the first character is always capitalized

this.name= name.charAt(0).toUpperCase() + name.slice(1)

this.gender = gender

// We are allowing the caller to pass in an array where the first index is the left eye and the 2nd is the right

// This is for convenience to make it easier for them.

// Or they can just pass in the eyes using the correct format if they want to

// We must transform it into the object format if they chose the array approach

// because some internal API uses this format

this.eyes =Array.isArray(eyes) ? { left: eye[0], right: eye[1] } : eyes

this.legs = legs

this.scent = scent

// Pretending some internal API changed the field name of the frog's tongue from "tongueWidth" to "width"

// Check for old implementation and migrate them to the new field name

constisOld='tongueWidth'in tongue

if (isOld) {

constnewTongue= { ...tongue }

delete newTongue['tongueWidth']

newTongue.width= tongue.width

this.tongue = newTongue

} else {

this.tongue = newTongue

}

this.heart = heart

if (typeof weight !=='undefined') {

this.weight = weight

}

if (typeof height !=='undefined') {

this.height= height

}

}

}

constlarry=newFrog(

'larry',

'male',

[{ volume:1.1 }, { volume:1.12 }],

[{ size:'small' }, { size:'small' }, { size:'small' }, { size:'small' }],

'sweaty socks',

{ tongueWidth:18, color:'dark red', type:'round' },

{ rate:22 },

6,

3.5,

)

Frog.js hosted with by GitHub

構造器代碼有點長,因為要處理不同參數,它的邏輯會被弄亂,因此在某些情況下,它甚至不需要很多的邏輯。這可能會讓代碼難懂,特別是在很久沒有看到原始碼的情況下。

如果我們在開發一個frog應用程式,並且想將其實例化,會有一個缺點:必須確保每個得到的參數在遵循函數籤名方面接近100%完美,否則在構建階段會有一些拋出。

如果需要在某個時候仔細檢查「眼睛」的類型,就必須在雜亂的代碼中尋找,才能得到我們要找的。

如果您最終找到了要查找的行,但隨後意識到有另一行代碼正在引用並影響50行之上的同一個參數,您會覺得困擾嗎?

現在你必須回溯一下,才能明白會發生什麼。

如果從前面的例子中再看一眼FrogBuilder構造函數,就能夠簡化構造器,使代碼變得不混亂且自然。

四、缺少控制

圖源:Unsplash

最重要的一項是從執行工作的更多控制中感受到好處。

在沒有建造者示例的時候,通過構造器中可以編寫更多的代碼,但嘗試在其中駐留的代碼越多,可讀性就越低,這會使代碼不清楚。

由於我們可以將細節隔離到各自的功能塊中,因此我們在許多方面有了更好的控制。

一種方法是,可以在不添加更多問題的情況下添加驗證,從而使構建階段更加堅實:

setHeart(heart) {

if (typeof heart !=='object') {

thrownewError('heart is not an object')

}

if (!('rate'in heart)) {

thrownewError('rate in heart is undefined')

}

// Assume the caller wants to pass in a callback to receive the current frog's weight and height that he or she has set

// previously so they can calculate the heart object on the fly. Useful for loops of collections

if (typeof heart ==='function') {

this.heart =heart({

weight:this.weight,

height:this.height

})

} else {

this.heart = heart

}

returnthis

}

validate() {

constrequiredFields= ['name', 'gender', 'eyes', 'legs', 'scent', 'tongue', 'heart']

for (let index =0; index < requiredFields.length; index++) {

constfield= requiredFields[index]

// Immediately return false since we are missing a parameter

if (!(field inthis)) {

returnfalse

}

}

returntrue

}

build() {

constisValid=this.validate(this)

if (isValid) {

returnnewFrog(

this.name,

this.gender,

this.eyes,

this.legs,

this.scent,

this.tongue,

this.heart,

this.weight,

this.height,

)

} else {

// just going to log to console

console.error('Parameters are invalid')

}

}

setHeart.js hosted with by GitHub

從這個例子可以看出,構建器的每一部分都是在添加驗證或驗證方法後獨立的,以確保在最終構建Frog之前設置好了所有的必需欄位。

還可以利用這些開放的機會添加更多自定義輸入數據類型,以構建參數的原始返回值。

例如,添加更多自定義的使用「眼睛」傳遞信息的方式,從而簡化整個過程:

formatEyesCorrectly(eyes) {

// Assume the caller wants to pass in an array where the first index is the left

// eye, and the 2nd is the right

if (Array.isArray(eyes)) {

return {

left: eye[0],

right: eye[1]

}

}

// Assume that the caller wants to use a number to indicate that both eyes have the exact same volume

if (typeof eyes ==='number') {

return {

left: { volume: eyes },

right: { volume: eyes },

}

}

// Assume that the caller might be unsure of what to set the eyes at this current moment, so he expects

// the current instance as arguments to their callback handler so they can calculate the eyes by themselves

if (typeof eyes ==='function') {

returneyes(this)

}

// Assume the caller is passing in the directly formatted object if the code gets here

return eyes

}

setEyes(eyes) {

this.eyes =this.formatEyes(eyes)

returnthis

}

FrogBuilder.js hosted with by GitHub

這樣一來,對於來電者來說,輸入什麼樣的數據類型就變得更靈活:

// variation 1 (left eye = index 1, right eye = index 2)

larry.setEyes([{ volume:1 }, { volume:1.2 }])

// variation 2 (left eye + right eye = same values)

larry.setEyes(1.1)

// variation 3 (the caller calls the shots on calculating the left and right eyes)

larry.setEyes(function(instance) {

let leftEye, rightEye

let weight, height

if ('weight'in instance) {

weight = instance.weight

}

if ('height'in instance) {

height = instance.height

}

if (weight >10) {

// It's a fat frog. Their eyes are probably humongous!

leftEye = { volume:5 }

rightEye = { volume:5 }

} else {

constvolume= someApi.getVolume(weight, height)

leftEye = { volume }

// Assuming that female frogs have shorter right eyes for some odd reason

rightEye = { volume: instance.gender ==='female'?0.8:1 }

}

return {

left: leftEye,

right: rightEye,

}

})

// variation 4 (caller decides to use the formatted object directly)

larry.setEyes({

left: { volume:1.5 },

right: { volume:1.51 },

})

larry.js hosted with by GitHub

以上就是全部內容啦~如果大家還有什麼問題,歡迎在評論區暢所欲言喲~

留言點讚關注

我們一起分享AI學習與發展的乾貨

如轉載,請後臺留言,遵守轉載規範

相關焦點

  • 【化繭成蝶】如何重拾學英語的信心
    有很多低級別的學生在學習過程中極易產生困惑或者失去信心。一種是胡亂攀比性的問題。很多學生會問「老師,我怎麼還不會說啊?老師,有什麼學習方法可以讓我快速提高啊?」其實,英語是一門語言,是需要長時間的積累的,不要指望有什麼捷徑可以一步登天。低級別的學生是最容易進步的,也是最容易看不到進步的。因為他們會習慣性的和高級別學生以及老師去比較,覺得自己學了這麼久還是不可以順利的開口說。
  • 如果你對生活失去了信心,居裡夫人的語錄,會讓你對生活重拾信心
    現實中大多數都是對生活沒有信心的,因為大多數人都是很窮,很缺錢,更是沒有房子,三四十歲還沒有討老婆的人。倘若他很有能力,會賺錢,現在已經在一線城市有好幾套房子了,而還是一位大企業的老總,也結婚生子了,人生幾乎不缺錢,他還會感到生活不容易嗎?如果依舊會感到,那也是對人類的,對別人,對自己曾經的遭遇感到同情罷了。
  • 七天學會javascript第一天javascript介紹
    前幾周寫了幾篇關於入門php的文章,反響還不錯,之前簡單的提到了JavaScript,這周小編重點介紹JavaScript讓大家可以在一周時間內掌握這門前端語言的基本用法。javascript介紹javascript數據類型javascript運算符javascript對象javascript Date對象javascript String對象JavaScript常用於實現一些前端效果。前些年流行的flash已經慢慢的被淘汰,js盛行起來。javascript :客戶端編程。javascript是由客戶端去解釋運行的。
  • JavaScript入門教程
    起源javascript前身叫做livescript,sun公司推出java,netspace公司引進java的概念,重新設計livescript,並更名javascript。發明者,布蘭登.艾克,表單驗證原先要經過伺服器,伺服器壓力大,等待時間長,js僅在客戶端就可完成。是什麼是一種腳本語言,是一種輕量級的程式語言。
  • 在JavaScript字符串的search()方法中,如何匹配正則表達式?
    第一節:基本概念#JavaScript#正則表達式已經成為各大程式語言的標準,只是在不同的語言中,所使用的方式有所不同,但基本上核心的功能都是一樣的。正則表達式的核心功能是建立一種匹配模式,這個匹配模式可以理解為模板,模子。然後再拿具體的字符串來與這個模式進行匹配,如果匹配上,則表示符合要求,則進一步採用措施。
  • Javascript去除字符串中的點或其他符號
    今天在寫一個前端頁面的時候遇到了一個ip參數問題,我想把ip值中的點替換成 - 的形式。在前端上使用javascript進行操作的。測試了兩次沒有好用,程序直接把整個字符串都進行了替換,在考慮這個是為什麼呢?
  • 在JavaScript中,使用replace()、test()和exec()方法匹配字符串
    01第一節:replace()方法概述在#JavaScript#中,replace()方法可以在字符串中使用一個或多個字符替換為另外一個或多個字符,也可以替換為一個與正則表達式能夠匹配上的子字符串。;var res = str.replace(/Microsoft/i, "Google");document.write(res);</script>replace()方法的參數說明如下:第1個參數可以是查找的字符串,也可以是一個正則表達式,此例子中是一個正則表達式。第2個參數是最終要替換為的新字符串。
  • JavaScript - Math對象
    中其實是有很多數學計算的需求的,不過不必擔心系統給我們提供了大量的數學運算的方法供我們使用而這些方法全都存在於我們的Math對象中Math常用的屬性:Math.PI 相當於π 3.14159Math對象常用的函數:1.Math.round() 四捨五入舉個小例子:<script type = 「text/javascript
  • 什麼是JavaScript對象?如何創建並引用?這就告訴你!
    因為對象能幫我們解決一些複雜的問題一、對象概述在JavaScript 中的所有事物都是對象:字符串(new String)、布爾(new Boolean())、數值(Number)、數組(Array)、函數(Function)等。1.1 什麼是類類:就是具有相同的屬性和方法的集合。人類,動物類,家電類等。
  • 三峽水華已查明癥結 負責人稱有信心解決問題
    三峽支流水華問題已存在數年,昨日,有關部門表示已找到癥結並有信心解決。三峽總公司副總經理曹廣晶昨日向本報表示,水華主要出現在三峽的一些支流上,這個問題從2005年以後一直存在。曹廣晶透露,三峽總公司經過幾年的監測和研究,已初步探明水華發生的一些機理,並在一些主要發生水華的支流上採取措施,諸如建立監測預警系統、在水中放置吃藻類的魚類等措施,「儘管現在還沒有完全解決,但是我對這個問題的解決非常有信心。」曹廣晶說。曹廣晶還表示:汶川地震對三峽大壩的影響非常小。據推算,影響大壩的地震烈度為4度,遠低於大壩設計的抗震烈度7度的標準。
  • 《我的世界》:海洋模式中呼吸成了問題,可以用海龜帽解決
    本文章由遊戲終結者鄧二哥獨家發布,各位朋友敞開的去閱讀吧~《我的世界》:海洋模式中呼吸成了問題,可以用海龜帽解決在海洋模式裡面,玩家處在一個周圍都是水的環境中,這個時候,呼吸就成了一個不能忽視的問題,那麼除了使用藥水之外,還有什麼方法可以幫助玩家在水中呼吸呢?
  • AJAXRPC: javascript調用服務端方法
    使用AJAXRPC,您可以像開發傳統的C/S程序一樣,來開發WEB程序,讓WEB開發更簡單和高效。 支持服務端語言:Java、.Net、PHP。 支持瀏覽器:IE、FireFox、Opera、Safari、Chrome。
  • 英媒報導中國奶奶感人故事 外國網友:她讓我重拾對人性的信心
    報導稱,她「4年如一日,風雨無阻,意志堅強。」  報導說,史玉英的孫子蔣昊文今年9歲,卻相當不幸:他患有腦癱,無法獨自行走,全天需要人看護。父母在他4歲時便離婚了,母親改嫁,父親去城裡打工維持家計,身邊只有年事已高的奶奶來照顧他。
  • 高中數學:讓你重拾信心的必修三知識點公式來了,拿去理解背誦吧
    終於讓學生們重拾信心,相信自己也可以學好數學。下面精選必修三的知識點與概念,及其相關公式,供新高一的同學參考學習!第一章 算法初步1、算法概念:在數學上,現代意義上的「算法」通常是指可以用計算機來解決的某一類問題是程序或步驟,這些程序或步驟必須是明確和有效的,而且能夠在有限步之內完成.
  • 因長相甜美被排擠,抑鬱後,通過健身重拾自信,並收穫完美身材
    今天,小編要介紹一位特別勵志的人,她曾經患有輕度抑鬱症,通過健身走出困境重拾信心。我希望每個人都能像她一樣以樂觀的態度面對生活中的各種挫折。她叫Celine Farach。她1997年出生於美國邁阿密,現在是一名模特兼歌手。因為她在學生時代的形象很高,被一家模特公司找到並籤約。
  • JavaScript中的「黑話」
    Array.prototype.push.apply在es5中,若想要對數組進行拼接操作,我們習慣於使用數組中的concat方法:let arrs =[1,2,3];arrs = arrs.concat([4,5,6]);但還有酷的方法,利用apply方法的數組傳參特性,可以更簡潔的執行拼接操作:const arrs =[1,2,3];arrs.push.apply
  • 50個實用的JavaScript工具
    安全工具  AttackAPI  AttackAPI是一個基於Web的攻擊構造庫,它可以結合PHP、JavaScript及其他客戶端和伺服器端技術進行使用。JavaScriptMVC應用了模型-視圖-控制器架構模式,把業務邏輯和表示分離,使得代碼更加模塊化。  qooxdoo  是一個功能強大基於JavaScript GUI工包,它讓你可以用JavaScript來開發類似於VB/Delphi風格的具有Ajax功能的web2.0應用程式。
  • 國外某公司解決鋼鐵生鏽問題,通過生鏽原理,用1000W雷射除鏽
    現在的工業技術越來越發達,鋼鐵的使用,在中國的漢代就進入了鐵器時代,鐵的使用歷史悠久,而且在近現代鐵也投入到大規模的使用當中,比如在修建巨大建築時就會大量使用鋼鐵,但是鋼材很容易生鏽,這就對建造者來說是一個巨大的損失,因為生鏽了的鋼鐵使用價值會大打折扣,不僅會侵蝕鋼鐵本身,而且對修建的工程也存在安全隱患
  • 武漢男子摘除眼球54年 公益手術助其重拾生活信心
    武漢男子摘除眼球54年 公益手術助其重拾生活信心發布時間:2021年01月15日 16:38 來源:中新網湖北   中新網湖北新聞1月15日電  (吳曉敏 彭錦雲)今年57歲的胡先生3歲時右眼被樹枝扎傷,導致眼球被迫摘除,幾十年來一直深感自卑,嚴重影響了正常的工作和社交。
  • javascript在自動化測試項目中的應用「軟體測試開發入門教程」
    或者在自動化測試中應用過可能很多朋友javascript都是在Html中應用。我們做測試就是會應用在自動化測試當中不管學什麼技術,都要活學活用。基礎比較差的朋友,如果你覺得前方高能,可以先去把基礎鞏固一下,我始終認為一個點如果你在網際網路行業,做測試工程師。