摘要:刪除不必要的代碼。而簡(jiǎn)化前的代碼包含的語法要素對(duì)于傳達(dá)代碼意義本身作用并不大。刪除不必要的代碼有時(shí)候,我們?cè)噲D為不必要的事物命名。例如,大多數(shù)情況下,你應(yīng)該省略僅僅用來當(dāng)做返回值的變量。你的函數(shù)名應(yīng)該已經(jīng)說明了關(guān)于函數(shù)返回值的信息。
原文地址
本文已在前端早讀課公眾號(hào)首發(fā):【第952期】JavaScript代碼風(fēng)格要素
譯者:墨白 校對(duì):野草
1920年,由威廉·斯特倫克(William Strunk jr .)撰寫的《英語寫作手冊(cè):風(fēng)格的要素(The Elements of Style)》出版了,這本書列舉了7條英文寫作的準(zhǔn)則,過了一個(gè)世紀(jì),這些準(zhǔn)則并沒有過時(shí)。對(duì)于工程師來說,你可以在自己的編碼風(fēng)格中應(yīng)用類似的建議來指導(dǎo)日常的編碼,提高自己的編碼水平。
需要注意的是,這些準(zhǔn)則不是一成不變的法則。如果違背它們,能夠讓代碼可讀性更高,那么便沒有問題,但請(qǐng)?zhí)貏e小心并時(shí)刻反思。這些準(zhǔn)繩是經(jīng)受住了時(shí)間考驗(yàn)的,有充分的理由說明:它們通常是正確的。如果要違背這些規(guī)則,一定要有充足的理由,而不要單憑一時(shí)的興趣或者個(gè)人的風(fēng)格偏好。
書中的寫作準(zhǔn)則如下:
以段落為基本單位:一段文字,一個(gè)主題。
刪減無用的語句。
使用主動(dòng)語態(tài)。
避免一連串松散的句子。
相關(guān)的內(nèi)容寫在一起。
從正面利用肯定語句去發(fā)表陳述。
不同的概念采用不同的結(jié)構(gòu)去闡述。
我們可以應(yīng)用相似的理念到代碼編寫上面:
一個(gè)function只做一件事,讓function成為代碼組合的最小單元。
刪除不必要的代碼。
使用主動(dòng)語態(tài)。
避免一連串結(jié)構(gòu)松散的,不知所云的代碼。
將相關(guān)的代碼寫在一起。
利用判斷true值的方式來編寫代碼。
不同的技術(shù)方案利用不同的代碼組織結(jié)構(gòu)來實(shí)現(xiàn)。
1.一個(gè)function只做一件事,讓function成為代碼組合的最小單元軟件開發(fā)的本質(zhì)是“組合”。 我們通過組合模塊,函數(shù)和數(shù)據(jù)結(jié)構(gòu)來構(gòu)建軟件。理解如果編寫以及組合方法是軟件開發(fā)人員的基本技能。
模塊是一個(gè)或多個(gè)function和數(shù)據(jù)結(jié)構(gòu)的簡(jiǎn)單集合,我們用數(shù)據(jù)結(jié)構(gòu)來表示程序狀態(tài),只有在函數(shù)執(zhí)行之后,程序狀態(tài)才會(huì)發(fā)生一些有趣的變化。
JavaScript中,可以將函數(shù)分為3種:
I/O 型函數(shù) (Communicating Functions):函數(shù)用來執(zhí)行I/O。
過程型函數(shù) (Procedural Functions):對(duì)一系列的指令序列進(jìn)行分組。
映射型函數(shù) (Mapping Functions):給定一些輸入,返回對(duì)應(yīng)的輸出。
有效的應(yīng)用程序都需要I/O,并且很多程序都遵循一定的程序執(zhí)行順序,這種情況下,程序中的大部分函數(shù)都會(huì)是映射型函數(shù):給定一些輸入,返回相應(yīng)的輸出。
每個(gè)函數(shù)只做一件事情:如果你的函數(shù)主要用于I/O,就不要在其中混入映射型代碼,反之亦然。嚴(yán)格根據(jù)定義來說,過程型函數(shù)違反了這一指導(dǎo)準(zhǔn)則,同時(shí)也違反了另一個(gè)指導(dǎo)準(zhǔn)則:避免一連串結(jié)構(gòu)松散,不知所云的代碼。
理想中的函數(shù)是一個(gè)簡(jiǎn)單的、明確的純函數(shù):
同樣的輸入,總是返回同樣的輸出。
無副作用。
也可以查看,“什么是純函數(shù)?”
2. 刪除不必要的代碼簡(jiǎn)潔的代碼對(duì)于軟件而言至關(guān)重要。更多的代碼意味更多的bug隱藏空間。更少的代碼 = 更少的bug隱藏空間 = 更少的bug
簡(jiǎn)潔的代碼讀起來更清晰,因?yàn)樗鼡碛懈叩摹靶旁氡取保洪喿x代碼時(shí)更容易從較少的語法噪音中篩選出真正有意義的部分。可以說,更少的代碼 = 更少的語法噪聲 = 更強(qiáng)的代碼含義信息傳達(dá)
借用《風(fēng)格的元素》這本書里面的一句話就是:簡(jiǎn)潔的代碼更健壯。
function secret (message) { return function () { return message; } };
可以簡(jiǎn)化成:
const secret = msg => () => msg;
對(duì)于那些熟悉簡(jiǎn)潔箭頭函數(shù)寫法的開發(fā)來說,可讀性更好。它省略了不必要的語法:大括號(hào),function關(guān)鍵字以及return語句。
而簡(jiǎn)化前的代碼包含的語法要素對(duì)于傳達(dá)代碼意義本身作用并不大。它存在的唯一意義只是讓那些不熟悉ES6語法的開發(fā)者更好的理解代碼。
ES6自2015年已經(jīng)成為語言標(biāo)準(zhǔn),是時(shí)候去學(xué)習(xí)它了。
刪除不必要的代碼有時(shí)候,我們?cè)噲D為不必要的事物命名。問題是人類的大腦在工作中可用的記憶資源有限,每個(gè)名稱都必須作為一個(gè)多帶帶的變量存儲(chǔ),占據(jù)工作記憶的存儲(chǔ)空間。
由于這個(gè)原因,有經(jīng)驗(yàn)的開發(fā)者會(huì)盡可能地刪除不必要的變量。
例如,大多數(shù)情況下,你應(yīng)該省略僅僅用來當(dāng)做返回值的變量。你的函數(shù)名應(yīng)該已經(jīng)說明了關(guān)于函數(shù)返回值的信息。看看下面的:
const getFullName = ({firstName, lastName}) => { const fullName = firstName + " " + lastName; return fullName; };
對(duì)比
const getFullName = ({firstName, lastName}) => ( firstName + " " + lastName );
另一個(gè)開發(fā)者通常用來減少變量名的做法是,利用函數(shù)組合以及point-free-style。
Point-free-style是一種定義函數(shù)方式,定義成一種與參數(shù)無關(guān)的合成運(yùn)算。實(shí)現(xiàn)point-free風(fēng)格常用的方式包括函數(shù)科里化以及函數(shù)組合。
讓我們來看一個(gè)函數(shù)科里化的例子:
const add2 = a => b => a + b; // Now we can define a point-free inc() // that adds 1 to any number. const inc = add2(1); inc(3); // 4
看一下inc()函數(shù)的定義方式。注意,它并未使用function關(guān)鍵字,或者=>語句。add2也沒有列出一系列的參數(shù),因?yàn)樵摵瘮?shù)不在其內(nèi)部處理一系列的參數(shù),相反,它返回了一個(gè)知道如何處理參數(shù)的新函數(shù)。
函數(shù)組合是將一個(gè)函數(shù)的輸出作為另一函數(shù)的輸入的過程。 也許你沒有意識(shí)到,你一直在使用函數(shù)組合。鏈?zhǔn)秸{(diào)用的代碼基本都是這個(gè)模式,比如數(shù)組操作時(shí)使用的.map(),Promise 操作時(shí)的promise.then()。函數(shù)組合在函數(shù)式語言中也被稱之為高階函數(shù),其基本形式為:f(g(x))。
當(dāng)兩個(gè)函數(shù)組合時(shí),無須創(chuàng)建一個(gè)變量來保存兩個(gè)函數(shù)運(yùn)行時(shí)的中間值。我們來看看函數(shù)組合是怎么減少代碼的:
const g = n => n + 1; const f = n => n * 2; // 需要操作參數(shù)、并且存儲(chǔ)中間結(jié)果 const incThenDoublePoints = n => { const incremented = g(n); return f(incremented); }; incThenDoublePoints(20); // 42 // compose2 - 接受兩個(gè)函數(shù)作為參數(shù),直接返回組合 const compose2 = (f, g) => x => f(g(x)); const incThenDoublePointFree = compose2(f, g); incThenDoublePointFree(20); // 42
你可以利用函子(functor)來做同樣的事情。在函子中把參數(shù)封裝成可遍歷的數(shù)組。讓我們利用函子來寫另一個(gè)版本的compose2:
const compose2 = (f, g) => x => [x].map(g).map(f).pop(); const incThenDoublePointFree = compose2(f, g); incThenDoublePointFree(20); // 42
當(dāng)每次使用promise鏈時(shí),你就是在做這樣的事情。
幾乎每一個(gè)函數(shù)式編程類庫都提供至少兩種函數(shù)組合方法:從右到左依次運(yùn)行的compose();從左到右依次運(yùn)行的pipe()。
Lodash中的compose()以及flow()分別對(duì)應(yīng)這兩個(gè)方法。下面是使用pipe的例子:
import pipe from "lodash/fp/flow"; pipe(g, f)(20); // 42
下面的代碼也做著同樣的事情,但代碼量并未增加太多:
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x); pipe(g, f)(20); // 42
如果函數(shù)組合這個(gè)名詞聽起來很陌生,你不知道如何使用它,請(qǐng)仔細(xì)想一想:
軟件開發(fā)的本質(zhì)是組合,我們通過組合較小的模塊,方法以及數(shù)據(jù)結(jié)構(gòu)來構(gòu)建應(yīng)用程序。
不難推論,工程師理解函數(shù)和對(duì)象組合這一編程技巧就如同搞裝修需要理解鉆孔機(jī)以及氣槍一樣重要。
當(dāng)你利用“命令式”代碼將功能以及中間變量拼湊在一起時(shí),就像瘋狂使用膠帶和膠水將這些部分胡亂粘貼起來一樣,而函數(shù)組合看上去更流暢。
記住:
用更少的代碼。
用更少的變量。
3. 使用主動(dòng)語態(tài)主動(dòng)語態(tài)比被動(dòng)語態(tài)更直接,跟有力量,盡量多直接命名事物:
myFunction.wasCalled()優(yōu)于myFunction.hasBeenCalled()
createUser優(yōu)于User.create()
notify()優(yōu)于Notifier.doNotification()
命名布爾返回值時(shí)最好直接反應(yīng)其輸出的類型:
isActive(user)優(yōu)于getActiveStatus(user)
isFirstRun = false;優(yōu)于firstRun = false;
函數(shù)名采用動(dòng)詞形式:
increment()優(yōu)于plusOne()
unzip()優(yōu)于filesFromZip()
filter(fn, array)優(yōu)于matchingItemsFromArray(fn, array)
事件處理事件處理以及生命周期函數(shù)由于是限定符,比較特殊,就不適用動(dòng)詞形式這一規(guī)則;相比于“做什么”,它們主要用來表達(dá)“什么時(shí)候做”。對(duì)于它們,可以“<什么時(shí)候去做>,<動(dòng)作>”這樣命名,朗朗上口。
element.onClick(handleClick)優(yōu)于element.click(handleClick)
element.onDragStart(handleDragStart)優(yōu)于component.startDrag(handleDragStart)
上面兩例的后半部分,它們讀起來更像是正在嘗試去觸發(fā)一個(gè)事件,而不是對(duì)其作出回應(yīng)。
生命周期函數(shù)對(duì)于組件生命周期函數(shù)(組件更新之前調(diào)用的方法),考慮一下以下的命名:
componentWillBeUpdated(doSomething)
componentWillUpdate(doSomething)
beforeUpdate(doSomething)
第一個(gè)種我們使用了被動(dòng)語態(tài)(將要被更新而不是將要更新)。這種方式很口語化,但含義表達(dá)并沒有比其它兩種方式更清晰。
第二種就好多了,但生命周期函數(shù)的重點(diǎn)在于觸發(fā)處理事件。componentWillUpdate(handler)讀起來就好像它將立即觸發(fā)一個(gè)處理事件,但這不是我們想要表達(dá)的。我們想說,“在組件更新之前,觸發(fā)事件”。beforeComponentUpdate()能更清楚的表達(dá)這一想法。
進(jìn)一步簡(jiǎn)化,因?yàn)檫@些方法都是組件內(nèi)置的。在方法名中加入component是多余的。想一想如果你直接調(diào)用這些方法時(shí):component.componentWillUpdate()。這就好像在說,“吉米吉米在晚餐吃牛排。”你沒有必要聽到同一個(gè)對(duì)象的名字兩次。顯然,
component.beforeUpdate(doSomething)優(yōu)于component.beforeComponentUpdate(doSomething)
函數(shù)混合是指將方法作為屬性添加到一個(gè)對(duì)象上面,它們就像裝配流水線給傳進(jìn)來的對(duì)象加上某些方法或者屬性。
我喜歡用形容詞來命名函數(shù)混合。你也可以經(jīng)常使用"ing"或者"able"后綴來找到有意義的形容詞。例如:
const duck = composeMixins(flying, quacking);
const box = composeMixins(iterable, mappable);
4.避免一連串結(jié)構(gòu)松散的,不知所云的代碼開發(fā)人員經(jīng)常將一系列事件串聯(lián)在一個(gè)進(jìn)程中:一組松散的、相關(guān)度不高的代碼被設(shè)計(jì)依次運(yùn)行。從而很容易形成“意大利面條”代碼。
這種寫法經(jīng)常被重復(fù)調(diào)用,即使不是嚴(yán)格意義上的重復(fù),也只有細(xì)微的差別。例如,界面不同組件之間幾乎共享相同的核心需求。 其關(guān)注點(diǎn)可以分解成不同生命周期階段,并由多帶帶的函數(shù)方法進(jìn)行管理。
考慮以下的代碼:
const drawUserProfile = ({ userId }) => { const userData = loadUserData(userId); const dataToDisplay = calculateDisplayData(userData); renderProfileData(dataToDisplay); };
這個(gè)方法做了三件事:獲取數(shù)據(jù),根據(jù)獲取的數(shù)據(jù)計(jì)算view的狀態(tài),以及渲染。
在大部分現(xiàn)代前端應(yīng)用中,這些關(guān)注點(diǎn)中的每一個(gè)都應(yīng)該考慮分拆開。通過分拆這些關(guān)注點(diǎn),我們可以輕松地為每個(gè)問題提供不同的函數(shù)。
比如,我們可以完全替換渲染器,它不會(huì)影響程序的其他部分。例如,React的豐富的自定義渲染器:適用于原生iOS和Android應(yīng)用程序的ReactNative,WebVR的AFrame,用于服務(wù)器端渲染的ReactDOM/Server 等等...
drawUserProfile的另一個(gè)問題就是你不能在沒有數(shù)據(jù)的情況下,簡(jiǎn)單地計(jì)算要展示的數(shù)據(jù)并生成標(biāo)簽。如果數(shù)據(jù)已經(jīng)在其他地方加載過了會(huì)怎么樣,就會(huì)做很多重復(fù)和浪費(fèi)的事情。
分拆關(guān)注點(diǎn)也使得它們更容易進(jìn)行測(cè)試。我喜歡對(duì)我的應(yīng)用程序進(jìn)行單元測(cè)試,并在每次修改代碼時(shí)查看測(cè)試結(jié)果。但是,如果我們將渲染代碼和數(shù)據(jù)加載代碼寫在一起,我不能簡(jiǎn)單地將一些假數(shù)據(jù)傳遞給渲染代碼進(jìn)行測(cè)試。我必須從端到端測(cè)試整個(gè)組件。而這個(gè)過程中,由于瀏覽器加載,異步I/O請(qǐng)求等等會(huì)耗費(fèi)時(shí)間。
上面的drawUserProfile代碼不能從單元測(cè)試測(cè)試中得到即時(shí)反饋。而分拆功能點(diǎn)允許你進(jìn)行多帶帶的單元測(cè)試,得到測(cè)試結(jié)果。
上文已經(jīng)已經(jīng)分析出多帶帶的功能點(diǎn),我們可以在應(yīng)用程序中提供不同的生命周期鉤子給其調(diào)用。 當(dāng)應(yīng)用程序開始裝載組件時(shí),可以觸發(fā)數(shù)據(jù)加載。可以根據(jù)響應(yīng)視圖狀態(tài)更新來觸發(fā)計(jì)算和渲染。
這么做的結(jié)果是軟件的職責(zé)進(jìn)一步明確:每個(gè)組件可以復(fù)用相同的結(jié)構(gòu)和生命周期鉤子,并且軟件性能更好。在后續(xù)開發(fā)中,我們不需要重復(fù)相同的事。
5.功能相連的代碼寫在一起許多框架以及boilerplates規(guī)定了程序文件組織的方法,其中文件按照代碼類別分組。如果你正在構(gòu)建一個(gè)小的計(jì)算器,獲取一個(gè)待辦事宜的app,這樣做是很好的。但是對(duì)于較大的項(xiàng)目,通過業(yè)務(wù)功能特性將文件分組在一起是更好的方法。
按代碼類別分組:
. ├── components │ ├── todos │ └── user ├── reducers │ ├── todos │ └── user └── tests ├── todos └── user
按業(yè)務(wù)功能特性分組:
. ├── todos │ ├── component │ ├── reducer │ └── test └── user ├── component ├── reducer └── test
當(dāng)你通過功能特性來將文件分組,你可以避免在文件列表上下滾動(dòng),查找編輯所需要的文件這種情況。
6.利用判斷true值的方式來編寫代碼要做出確定的斷言,避免使用溫順、無色、猶豫的語句,必要時(shí)使用 not 來否定、拒絕。典型的
isFlying優(yōu)于isNotFlying
late優(yōu)于notOneTime
if語句if (err) return reject(err); // do something
優(yōu)于
if (!err) { // ... do something } else { return reject(err); }三元判斷語句
{ [Symbol.iterator]: iterator ? iterator : defaultIterator }
優(yōu)于
{ [Symbol.iterator]: (!iterator) ? defaultIterator : iterator }恰當(dāng)?shù)氖褂梅穸?/b>
有時(shí)候我們只關(guān)心一個(gè)變量是否缺失,如果通過判斷true值的方式來命名,我們得用!操作符來否定它。這種情況下使用 "not" 前綴和取反操作符不如使用否定語句直接。
if (missingValue)優(yōu)于if (!hasValue)
if (anonymous)優(yōu)于if (!user)
if (!isEmpty(thing))優(yōu)于if (notDefined(thing))
函數(shù)調(diào)用時(shí),避免用null以及undefined代替某一個(gè)參數(shù)不要在函數(shù)調(diào)用時(shí),傳入undefined或者null作為某個(gè)參數(shù)的值。如果某些參數(shù)可以缺失,更推薦傳入一個(gè)對(duì)象:
const createEvent = ({ title = "Untitled", timeStamp = Date.now(), description = "" }) => ({ title, description, timeStamp }); const birthdayParty = createEvent({ title: "Birthday Party", description: "Best party ever!" });
優(yōu)于
const createEvent = ( title = "Untitled", timeStamp = Date.now(), description = "" ) => ({ title, description, timeStamp }); const birthdayParty = createEvent( "Birthday Party", undefined, // This was avoidable "Best party ever!" );不同的技術(shù)方案利用不同的代碼組織結(jié)構(gòu)來實(shí)現(xiàn)
迄今為止,應(yīng)用程序中未解決的問題很少。最終,我們都會(huì)一次又一次地做著同樣的事情。當(dāng)這樣的場(chǎng)景發(fā)生時(shí),意味著代碼重構(gòu)的機(jī)會(huì)來啦。分辨出類似的部分,然后抽取出能夠支持每個(gè)不同部分的公共方法。這正是類庫以及框架為我們做的事情。
UI組件就是一個(gè)很好的例子。10 年前,使用 jQuery 寫出把界面更新、應(yīng)用邏輯和數(shù)據(jù)加載混在一起的代碼是再常見不過的。漸漸地,人們開始意識(shí)到我們可以將MVC應(yīng)用到客戶端的網(wǎng)頁上面,隨后,人們開始將model與UI更新邏輯分拆。
最終,web應(yīng)用廣泛采用組件化這一方案,這使得我們可以使用JSX或HTML模板來聲明式的對(duì)組件進(jìn)行建模。
最終,我們就能用完全相同的方式去表達(dá)所有組件的更新邏輯、生命周期,而不用再寫一堆命令式的代碼
對(duì)于熟悉組件的人,很容易看懂每個(gè)組件的原理:利用標(biāo)簽來表示UI元素,事件處理器用來觸發(fā)行為,以及用于添加回調(diào)的生命周期鉤子函數(shù),這些鉤子函數(shù)將在必要時(shí)運(yùn)行。
當(dāng)我們對(duì)于類似的問題采用類似的模式解決時(shí),熟悉這個(gè)解決模式的人很快就能理解代碼是用來做什么的。
結(jié)論:代碼應(yīng)該簡(jiǎn)單而不是過于簡(jiǎn)單化盡管在2015,ES6已經(jīng)標(biāo)準(zhǔn)化,但在2017,很多開發(fā)者仍然拒絕使用ES6特性,例如箭頭函數(shù),隱式return,rest以及spread操作符等等。利用自己熟悉的方式編寫代碼其實(shí)是一個(gè)幌子,這個(gè)說法是錯(cuò)誤的。只有不斷嘗試,才能夠漸漸熟悉,熟悉之后,你會(huì)發(fā)現(xiàn)簡(jiǎn)潔的ES6特性明顯優(yōu)于ES5:與語法結(jié)構(gòu)偏重的ES5相比,簡(jiǎn)潔的es6的代碼很簡(jiǎn)單。
代碼應(yīng)該簡(jiǎn)單,而不是過于簡(jiǎn)單化。
簡(jiǎn)潔的代碼有以下優(yōu)勢(shì):
更少的bug可能性
更容易去debug
但也有如下弊端:
修復(fù)bug的成本更高
有可能引用更多的bug
打斷了正常開發(fā)的流程
簡(jiǎn)潔的代碼同樣:
更易寫
更易讀
更好去維護(hù)
清楚自己的目標(biāo),不要毫無頭緒。毫無頭緒只會(huì)浪費(fèi)時(shí)間以及精力。投入精力去訓(xùn)練,讓自己熟悉,去學(xué)習(xí)更好的編程方式,以及更有更有活力的代碼風(fēng)格。
代碼應(yīng)該簡(jiǎn)單,而不是簡(jiǎn)單化。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/83286.html
摘要:高德地圖入門一準(zhǔn)備工作首先注冊(cè)個(gè)開發(fā)者賬號(hào)然后創(chuàng)建應(yīng)用,獲取新建文件,在標(biāo)簽中引入如下代碼把你的值填入即可您申請(qǐng)的值創(chuàng)建設(shè)置地圖容器地圖初始化創(chuàng)建地圖設(shè)置地圖參數(shù)可以通過以下設(shè)置也可通過對(duì)象的方法設(shè)置預(yù)覽個(gè)性化地圖改變地圖樣式目前支持五種地 高德地圖 Javascript API 入門(一) 準(zhǔn)備工作 首先注冊(cè)個(gè)開發(fā)者賬號(hào) showImg(https://segmentfault.co...
摘要:前端每周清單第期支付寶前端構(gòu)建工具發(fā)展用加快網(wǎng)頁響應(yīng)速度餓了么升級(jí)實(shí)踐前端前端每周清單前端每周清單專注前端領(lǐng)域內(nèi)容,分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。 前端每周清單第 12 期:支付寶前端構(gòu)建工具發(fā)展、LinkedIn用Brotli加快網(wǎng)頁響應(yīng)速度、餓了么PWA 升級(jí)實(shí)踐 為InfoQ中文站特供稿件,首發(fā)地址為這里;如需轉(zhuǎn)載,請(qǐng)與InfoQ中文站聯(lián)系。從屬于筆...
摘要:最近讀完編寫可維護(hù)的,讓我受益匪淺,它指明了編碼過程中,需要注意的方方面面,在團(tuán)隊(duì)協(xié)作中特別有用,可維護(hù)性是一個(gè)非常大的話題,這本書是一個(gè)不錯(cuò)的起點(diǎn)。擴(kuò)展閱讀編寫可維護(hù)的歡迎來到石佳劼的博客,如有疑問,請(qǐng)?jiān)谠脑u(píng)論區(qū)留言,我會(huì)盡量為您解答。 最近讀完《編寫可維護(hù)的JavaScript》,讓我受益匪淺,它指明了編碼過程中,需要注意的方方面面,在團(tuán)隊(duì)協(xié)作中特別有用,可維護(hù)性是一個(gè)非常大的話...
摘要:和比特幣協(xié)議有所不同的是,以太坊的設(shè)計(jì)十分靈活,極具適應(yīng)性。超級(jí)賬本區(qū)塊鏈的商業(yè)應(yīng)用超級(jí)賬本超級(jí)賬本是基金會(huì)下的眾多項(xiàng)目中的一個(gè)。證書頒發(fā)機(jī)構(gòu)負(fù)責(zé)簽發(fā)撤 showImg(https://segmentfault.com/img/bV2ge9?w=900&h=385); 從比特幣開始 一個(gè)故事告訴你比特幣的原理及運(yùn)作機(jī)制 這篇文章的定位會(huì)比較科普,盡量用類比的方法將比特幣的基本原理講出來...
摘要:定制元素可以在原生元素外創(chuàng)建定制元素。此定制元素內(nèi)部有一個(gè)加號(hào)按鈕,一個(gè)減號(hào)按鈕,一個(gè)顯示當(dāng)前值。此主題會(huì)在下一部分內(nèi)介紹。定制元素的屬性元素的屬性被稱為,對(duì)象內(nèi)的屬性被稱為。做響應(yīng)的同步處理。 Web Components 全攬 Web Components技術(shù)可以把一組相關(guān)的HTML、JS代碼和CSS風(fēng)格打包成為一個(gè)自包含的組件,只要使用大家熟悉的標(biāo)簽即可引入此組件。Web Com...
閱讀 2770·2021-11-23 09:51
閱讀 3529·2021-10-08 10:17
閱讀 1262·2021-10-08 10:05
閱讀 1310·2021-09-28 09:36
閱讀 1833·2021-09-13 10:30
閱讀 2174·2021-08-17 10:12
閱讀 1670·2019-08-30 15:54
閱讀 2004·2019-08-30 15:53