本篇內(nèi)容主要講解“分析JavaScript代碼整潔之道”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“分析JavaScript代碼整潔之道”吧!
成都創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過去的十載時(shí)間我們累計(jì)服務(wù)了上千家以及全國政企客戶,如陽臺(tái)護(hù)欄等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過硬的技術(shù)實(shí)力獲得客戶的一致表揚(yáng)。1. 用命名的變量代替數(shù)組下標(biāo)
// bad const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; saveCityZipCode( // 下標(biāo)1,2不易于理解 address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2] );
// good const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; // 使用數(shù)組解構(gòu)更好的命名變量 const [, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode);
2. 函數(shù)的參數(shù)最好<=2個(gè),盡量避免3個(gè)。
如果有很多參數(shù)就利用object傳遞,并使用解構(gòu)。
3. 一個(gè)函數(shù)只做一件事。
好處在于compose, test, and reason about。
4. 不要自行擴(kuò)展原型
如果想擴(kuò)展原型,可以先繼承再添加方法,防止污染。
// bad Array.prototype.diff = function diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); };
// good class SuperArray extends Array { diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); } }
5. 用多態(tài)來代替條件語句
// bad if (type === 'text') { // do something } else if (type === 'select') { // do something else }
個(gè)人寫這種代碼的一種常用方式是:
const control = { text: { mapper() {}, restore(){}, name: 'this is a text field', }, select: { mapper() {}, restore(){}, name: 'this is a select field', } } control[type].mapper();
實(shí)際上就是多態(tài)(polymorphism),也可以考慮用class的方式,大概這樣:
class Field { ... } class TextField extends Field { mapper(){} restore(){} name = 'this is a text field'; } class SelectField extends Field { mapper(){} restore(){} name = 'this i```s a select field'; }
使用getter和setter函數(shù)。
// bad function makeBankAccount() { // ... return { balance: 0 // ... }; } const account = makeBankAccount(); account.balance = 100;
// good function makeBankAccount() { // this one is private let balance = 0; // a "getter", made public via the returned object below function getBalance() { return balance; } // a "setter", made public via the returned object below function setBalance(amount) { // ... validate before updating the balance balance = amount; } return { // ... getBalance, setBalance }; } const account = makeBankAccount(); account.setBalance(100);
你可以在getter和setter里面做很多事情而不需要修改每一個(gè).balance的地方。
7. Prefer composition over inheritance
盡量用組合來代替繼承,什么情況下用繼承:
Your inheritance represents an "is-a" relationship and not a "has-a" relationship (Human->Animal vs. User->UserDetails).
You can reuse code from the base classes (Humans can move like all animals).
You want to make global changes to derived classes by changing a base class. (Change the caloric expenditure of all animals when they move).
8. SOLID
Single Responsibility Principle 單一職責(zé)原則
There should never be more than one reason for a class to change,一個(gè)類被改變的原因數(shù)量應(yīng)該盡可能降低。如果一個(gè)類中---功能太多,當(dāng)你修改其中一點(diǎn)時(shí)會(huì)無法估量任何引用該類的模塊所受到的影響。
Open/Closed Principle 開放封閉原則
用戶可以在不修改內(nèi)部實(shí)現(xiàn)的前提下自行擴(kuò)展功能。例如有一個(gè)Http模塊,內(nèi)部會(huì)根據(jù)環(huán)境判斷用哪個(gè)adaptor。如果用戶要添加adaptor就必須修改Http模塊。
// bad class AjaxAdapter extends Adapter { constructor() { super(); this.name = "ajaxAdapter"; } } class NodeAdapter extends Adapter { constructor() { super(); this.name = "nodeAdapter"; } } class HttpRequester { constructor(adapter) { this.adapter = adapter; } fetch(url) { if (this.adapter.name === "ajaxAdapter") { return makeAjaxCall(url).then(response => { // transform response and return }); } else if (this.adapter.name === "nodeAdapter") { return makeHttpCall(url).then(response => { // transform response and return }); } } } function makeAjaxCall(url) { // request and return promise } function makeHttpCall(url) { // request and return promise }
// good class AjaxAdapter extends Adapter { constructor() { super(); this.name = "ajaxAdapter"; } request(url) { // request and return promise } } class NodeAdapter extends Adapter { constructor() { super(); this.name = "nodeAdapter"; } request(url) { // request and return promise } } class HttpRequester { constructor(adapter) { this.adapter = adapter; } fetch(url) { return this.adapter.request(url).then(response => { // transform response and return }); } }
Liskov Substitution Principle 里式替換原則
父類和子類應(yīng)該可以被交換使用而不會(huì)出錯(cuò)。
// bad class Rectangle { constructor() { this.width = 0; this.height = 0; } setColor(color) { // ... } render(area) { // ... } setWidth(width) { this.width = width; } setHeight(height) { this.height = height; } getArea() { return this.width * this.height; } } class Square extends Rectangle { setWidth(width) { this.width = width; this.height = width; } setHeight(height) { this.width = height; this.height = height; } } function renderLargeRectangles(rectangles) { rectangles.forEach(rectangle => { rectangle.setWidth(4); rectangle.setHeight(5); const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. rectangle.render(area); }); } const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles);
上面的Rectangle不能直接替換Square,因?yàn)闀?huì)導(dǎo)致計(jì)算面積錯(cuò)誤,考慮將計(jì)算面積的方法抽象出來:
class Shape { setColor(color) { // ... } render(area) { // ... } } class Rectangle extends Shape { constructor(width, height) { super(); this.width = width; this.height = height; } getArea() { return this.width * this.height; } } class Square extends Shape { constructor(length) { super(); this.length = length; } getArea() { return this.length * this.length; } } function renderLargeShapes(shapes) { shapes.forEach(shape => { const area = shape.getArea(); shape.render(area); }); } const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; renderLargeShapes(shapes);
Interface Segregation Principle 接口隔離原則
Clients should not be forced to depend upon interfaces that they do not use。舉例來說,一個(gè)功能模塊需要設(shè)計(jì)必須傳的參數(shù)和可選參數(shù),不應(yīng)該強(qiáng)迫用戶使用可選參數(shù)。
Dependency Inversion Principle 依賴注入原則
// bad class InventoryRequester { constructor() { this.REQ_METHODS = ["HTTP"]; } requestItem(item) { // ... } } class InventoryTracker { constructor(items) { this.items = items; // BAD: We have created a dependency on a specific request implementation. // We should just have requestItems depend on a request method: `request` this.requester = new InventoryRequester(); } requestItems() { this.items.forEach(item => { this.requester.requestItem(item); }); } } const inventoryTracker = new InventoryTracker(["apples", "bananas"]); inventoryTracker.requestItems();
上面例子在于,InventoryTracker內(nèi)部實(shí)例化了InventoryRequester,也就意味著high-level的模塊需要知道low-level模塊的細(xì)節(jié)(比如實(shí)例化InventoryRequester需要知道它的構(gòu)造參數(shù)等,或者說需要import該模塊,造成耦合)。
// good class InventoryTracker { constructor(items, requester) { this.items = items; this.requester = requester; } requestItems() { this.items.forEach(item => { this.requester.requestItem(item); }); } } class InventoryRequesterV1 { constructor() { this.REQ_METHODS = ["HTTP"]; } requestItem(item) { // ... } } class InventoryRequesterV2 { constructor() { this.REQ_METHODS = ["WS"]; } requestItem(item) { // ... } } // By constructing our dependencies externally and injecting them, we can easily // substitute our request module for a fancy new one that uses WebSockets. const inventoryTracker = new InventoryTracker( ["apples", "bananas"], new InventoryRequesterV2() ); inventoryTracker.requestItems();
直接傳入low-level的實(shí)例而不需要考慮它是如何被實(shí)例化的,high-level只需要依賴抽象的接口就可以完成對(duì)子模塊的調(diào)用。
9. 注釋
Comments are an apology, not a requirement. Good code mostly documents itself. 好的代碼是自解釋的。
你會(huì)經(jīng)常地遇到 bug 和其它一些問題。這可能會(huì)讓人沮喪,但你要盡量保持冷靜,并系統(tǒng)地去思考。記住實(shí)踐是解決問題的最佳方法。
到此,相信大家對(duì)“分析JavaScript代碼整潔之道”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
本文名稱:分析JavaScript代碼整潔之道-創(chuàng)新互聯(lián)
鏈接分享:http://vcdvsql.cn/article2/eghoc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、虛擬主機(jī)、網(wǎng)站策劃、商城網(wǎng)站、網(wǎng)站改版、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容