這篇文章主要介紹“怎么寫出優(yōu)雅耐看的JavaScript代碼”,在日常操作中,相信很多人在怎么寫出優(yōu)雅耐看的JavaScript代碼問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么寫出優(yōu)雅耐看的JavaScript代碼”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
富源網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,富源網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為富源上1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的富源做網(wǎng)站的公司定做!
1、變量命名
一般我們在定義變量是要使用有意義的詞匯命令,要做到見面知義
//bad code const yyyymmdstr = moment().format('YYYY/MM/DD'); //better code const currentDate = moment().format('YYYY/MM/DD');
2、可描述
通過一個變量生成了一個新變量,也需要為這個新變量命名,也就是說每個變量當你看到他第一眼你就知道他是干什么的。
//bad code const ADDRESS = 'One Infinite Loop, Cupertino 95014'; const CITY_ZIP_CODE_REGEX = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; saveCityZipCode(ADDRESS.match(CITY_ZIP_CODE_REGEX)[1], ADDRESS.match(CITY_ZIP_CODE_REGEX)[2]); //better code const ADDRESS = 'One Infinite Loop, Cupertino 95014'; const CITY_ZIP_CODE_REGEX = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; const [, city, zipCode] = ADDRESS.match(CITY_ZIP_CODE_REGEX) || []; saveCityZipCode(city, zipCode);
3、形參命名
在for、forEach、map的循環(huán)中我們在命名時要直接
//bad code const locations = ['Austin', 'New York', 'San Francisco']; locations.map((l) => { doStuff(); doSomeOtherStuff(); // ... // ... // ... // 需要看其他代碼才能確定 'l' 是干什么的。 dispatch(l); }); //better code const locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((location) => { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch(location); });
4、避免無意義的前綴
例如我們只創(chuàng)建一個對象是,沒有必要再把每個對象的屬性上再加上對象名
//bad code const car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' }; function paintCar(car) { car.carColor = 'Red'; } //better code const car = { make: 'Honda', model: 'Accord', color: 'Blue' }; function paintCar(car) { car.color = 'Red'; }
5、默認值
//bad code function createMicrobrewery(name) { const breweryName = name || 'Hipster Brew Co.'; // ... } //better code function createMicrobrewery(name = 'Hipster Brew Co.') { // ... }
1、參數(shù)
一般參數(shù)多的話要使用ES6的解構(gòu)傳參的方式
//bad code function createMenu(title, body, buttonText, cancellable) { // ... } //better code function createMenu({ title, body, buttonText, cancellable }) { // ... } //better code createMenu({ title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true });
2、單一化處理
一個方法里面最好只做一件事,不要過多的處理,這樣代碼的可讀性非常高
//bad code function emailClients(clients) { clients.forEach((client) => { const clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } }); } //better code function emailActiveClients(clients) { clients .filter(isActiveClient) .forEach(email); } function isActiveClient(client) { const clientRecord = database.lookup(client); return clientRecord.isActive(); }
3、對象設(shè)置默認屬性
//bad code const menuConfig = { title: null, body: 'Bar', buttonText: null, cancellable: true }; function createMenu(config) { config.title = config.title || 'Foo'; config.body = config.body || 'Bar'; config.buttonText = config.buttonText || 'Baz'; config.cancellable = config.cancellable !== undefined ? config.cancellable : true; } createMenu(menuConfig); //better code const menuConfig = { title: 'Order', // 'body' key 缺失 buttonText: 'Send', cancellable: true };
4、避免副作用
函數(shù)接收一個值返回一個新值,除此之外的行為我們都稱之為副作用,比如修改全局變量、對文件進行 IO 操作等。
當函數(shù)確實需要副作用時,比如對文件進行 IO 操作時,請不要用多個函數(shù)/類進行文件操作,有且僅用一個函數(shù)/類來處理。也就是說副作用需要在唯一的地方處理。
副作用的三大天坑:隨意修改可變數(shù)據(jù)類型、隨意分享沒有數(shù)據(jù)結(jié)構(gòu)的狀態(tài)、沒有在統(tǒng)一地方處理副作用。
//bad code // 全局變量被一個函數(shù)引用 // 現(xiàn)在這個變量從字符串變成了數(shù)組,如果有其他的函數(shù)引用,會發(fā)生無法預見的錯誤。 var name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); } splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott']; //better code var name = 'Ryan McDermott'; var newName = splitIntoFirstAndLastName(name) function splitIntoFirstAndLastName(name) { return name.split(' '); } console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott'];
在 JavaScript 中,基本類型通過賦值傳遞,對象和數(shù)組通過引用傳遞。以引用傳遞為例:
假如我們寫一個購物車,通過 addItemToCart()方法添加商品到購物車,修改 購物車數(shù)組。此時調(diào)用 purchase()方法購買,由于引用傳遞,獲取的 購物車數(shù)組正好是最新的數(shù)據(jù)。
看起來沒問題對不對?
如果當用戶點擊購買時,網(wǎng)絡(luò)出現(xiàn)故障, purchase()方法一直在重復調(diào)用,與此同時用戶又添加了新的商品,這時網(wǎng)絡(luò)又恢復了。那么 purchase()方法獲取到 購物車數(shù)組就是錯誤的。
為了避免這種問題,我們需要在每次新增商品時,克隆 購物車數(shù)組并返回新的數(shù)組。
//bad code const addItemToCart = (cart, item) => { cart.push({ item, date: Date.now() }); }; //better code const addItemToCart = (cart, item) => { return [...cart, {item, date: Date.now()}] };
5、全局方法
在 JavaScript 中,永遠不要污染全局,會在生產(chǎn)環(huán)境中產(chǎn)生難以預料的 bug。舉個例子,比如你在 Array.prototype上新增一個 diff方法來判斷兩個數(shù)組的不同。而你同事也打算做類似的事情,不過他的 diff方法是用來判斷兩個數(shù)組首位元素的不同。很明顯你們方法會產(chǎn)生沖突,遇到這類問題我們可以用 ES2015/ES6 的語法來對 Array進行擴展。
//bad code Array.prototype.diff = function diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); }; //better code class SuperArray extends Array { diff(comparisonArray) { const hash = new Set(comparisonArray); return this.filter(elem => !hash.has(elem)); } }
6、避免類型檢查
JavaScript 是無類型的,意味著你可以傳任意類型參數(shù),這種自由度很容易讓人困擾,不自覺的就會去檢查類型。仔細想想是你真的需要檢查類型還是你的 API 設(shè)計有問題?
//bad code function travelToTexas(vehicle) { if (vehicle instanceof Bicycle) { vehicle.pedal(this.currentLocation, new Location('texas')); } else if (vehicle instanceof Car) { vehicle.drive(this.currentLocation, new Location('texas')); } } //better code function travelToTexas(vehicle) { vehicle.move(this.currentLocation, new Location('texas')); }
如果你需要做靜態(tài)類型檢查,比如字符串、整數(shù)等,推薦使用 TypeScript,不然你的代碼會變得又臭又長。
//bad code function combine(val1, val2) { if (typeof val1 === 'number' && typeof val2 === 'number' || typeof val1 === 'string' && typeof val2 === 'string') { return val1 + val2; } throw new Error('Must be of type String or Number'); } //better code function combine(val1, val2) { return val1 + val2; }
我們編寫js代碼時經(jīng)常遇到復雜邏輯判斷的情況,通常大家可以用if/else或者switch來實現(xiàn)多個條件判斷,但這樣會有個問題,隨著邏輯復雜度的增加,代碼中的if/else/switch會變得越來越臃腫,越來越看不懂,那么如何更優(yōu)雅的寫判斷邏輯
1、if/else
點擊列表按鈕事件
/** * 按鈕點擊事件 * @param {number} status 活動狀態(tài):1 開團進行中 2 開團失敗 3 商品售罄 4 開團成功 5 系統(tǒng)取消 */ const onButtonClick = (status)=>{ if(status == 1){ sendLog('processing') jumpTo('IndexPage') }else if(status == 2){ sendLog('fail') jumpTo('FailPage') }else if(status == 3){ sendLog('fail') jumpTo('FailPage') }else if(status == 4){ sendLog('success') jumpTo('SuccessPage') }else if(status == 5){ sendLog('cancel') jumpTo('CancelPage') }else { sendLog('other') jumpTo('Index') } }
從上面我們可以看到的是通過不同的狀態(tài)來做不同的事情,代碼看起來非常不好看,大家可以很輕易的提出這段代碼的改寫方案,switch出場:
2、switch/case
/** * 按鈕點擊事件 * @param {number} status 活動狀態(tài):1 開團進行中 2 開團失敗 3 商品售罄 4 開團成功 5 系統(tǒng)取消 */ const onButtonClick = (status)=>{ switch (status){ case 1: sendLog('processing') jumpTo('IndexPage') break case 2: case 3: sendLog('fail') jumpTo('FailPage') break case 4: sendLog('success') jumpTo('SuccessPage') break case 5: sendLog('cancel') jumpTo('CancelPage') break default: sendLog('other') jumpTo('Index') break } }
這樣看起來比if/else清晰多了,細心的同學也發(fā)現(xiàn)了小技巧,case 2和case 3邏輯一樣的時候,可以省去執(zhí)行語句和break,則case 2的情況自動執(zhí)行case 3的邏輯。
3、存放到Object
將判斷條件作為對象的屬性名,將處理邏輯作為對象的屬性值,在按鈕點擊的時候,通過對象屬性查找的方式來進行邏輯判斷,這種寫法特別適合一元條件判斷的情況。
const actions = { '1': ['processing','IndexPage'], '2': ['fail','FailPage'], '3': ['fail','FailPage'], '4': ['success','SuccessPage'], '5': ['cancel','CancelPage'], 'default': ['other','Index'], } /** * 按鈕點擊事件 * @param {number} status 活動狀態(tài):1開團進行中 2開團失敗 3 商品售罄 4 開團成功 5 系統(tǒng)取消 */ const onButtonClick = (status)=>{ let action = actions[status] || actions['default'], logName = action[0], pageName = action[1] sendLog(logName) jumpTo(pageName) }
4、存放到Map
const actions = new Map([ [1, ['processing','IndexPage']], [2, ['fail','FailPage']], [3, ['fail','FailPage']], [4, ['success','SuccessPage']], [5, ['cancel','CancelPage']], ['default', ['other','Index']] ]) /** * 按鈕點擊事件 * @param {number} status 活動狀態(tài):1 開團進行中 2 開團失敗 3 商品售罄 4 開團成功 5 系統(tǒng)取消 */ const onButtonClick = (status)=>{ let action = actions.get(status) || actions.get('default') sendLog(action[0]) jumpTo(action[1]) }
這樣寫用到了es6里的Map對象,是不是更爽了?Map對象和Object對象有什么區(qū)別呢?
一個對象通常都有自己的原型,所以一個對象總有一個"prototype"鍵。
一個對象的鍵只能是字符串或者Symbols,但一個Map的鍵可以是任意值。
你可以通過size屬性很容易地得到一個Map的鍵值對個數(shù),而對象的鍵值對個數(shù)只能手動確認。
常量大寫
//bad code const DAYS_IN_WEEK = 7; const daysInMonth = 30; const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restore_database() {} class animal {} class Alpaca {} //better code const DAYS_IN_WEEK = 7; const DAYS_IN_MONTH = 30; const SONGS = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']; const ARTISTS = ['ACDC', 'Led Zeppelin', 'The Beatles']; function eraseDatabase() {} function restoreDatabase() {} class Animal {} class Alpaca {}
先聲明后調(diào)用
//bad code class PerformanceReview { constructor(employee) { this.employee = employee; } lookupPeers() { return db.lookup(this.employee, 'peers'); } lookupManager() { return db.lookup(this.employee, 'manager'); } getPeerReviews() { const peers = this.lookupPeers(); // ... } perfReview() { this.getPeerReviews(); this.getManagerReview(); this.getSelfReview(); } getManagerReview() { const manager = this.lookupManager(); } getSelfReview() { // ... } } const review = new PerformanceReview(employee); review.perfReview(); //better code class PerformanceReview { constructor(employee) { this.employee = employee; } perfReview() { this.getPeerReviews(); this.getManagerReview(); this.getSelfReview(); } getPeerReviews() { const peers = this.lookupPeers(); // ... } lookupPeers() { return db.lookup(this.employee, 'peers'); } getManagerReview() { const manager = this.lookupManager(); } lookupManager() { return db.lookup(this.employee, 'manager'); } getSelfReview() { // ... } } const review = new PerformanceReview(employee); review.perfReview();
到此,關(guān)于“怎么寫出優(yōu)雅耐看的JavaScript代碼”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
分享標題:怎么寫出優(yōu)雅耐看的JavaScript代碼
標題來源:http://weahome.cn/article/igesci.html