這確實是一篇針對於基於 JavaScript 語言編程的開發者必讀的文章。在過去幾年我學習 JavaScript 的時候,我寫下了這篇文章,並將其做爲 JavaScript 快速編程技巧的一個重要參考。爲了有助於理解,針對常規寫法我也給出了相關的編程觀點。javascript
2017 年 6 月 14 日:這篇文章更新了一些基於 ES6 的速記寫法。若是你想進一步瞭解 ES6 中有哪些新增的變化,能夠註冊 SitePoint Premium 並查看咱們錄製的視頻 A Look into ES6.html
若是你想只用一行代碼寫出一個 if..else 表達式,那麼這是一個很好的節省代碼的方式。java
常規寫法:es6
const x = 20; let answer; if (x > 10) { answer = 'is greater'; } else { answer = 'is lesser'; }
速記法:web
const answer = x > 10 ? 'is greater' : 'is lesser';
你也能夠像這樣嵌套 if 表達式:編程
const big = x > 10 ? " greater 10" : x
當須要給另外一個變量分配一個變量時,你可能須要確保變量不是 null、undefined 或者不爲空。你能夠寫一個有多個 if 表達式的語句,你也可使用短路求值。數組
常規寫法:框架
if (variable1 !== null || variable1 !== undefined || variable1 !== '') { let variable2 = variable1; }
速記法:less
const variable2 = variable1 || 'new';
你不相信這樣能夠 work?那就本身測試下吧(把下面的代碼複製粘貼到 es6console:編程語言
let variable1; let variable2 = variable1 || ''; console.log(variable2 === ''); // prints true variable1 = 'foo'; variable2 = variable1 || ''; console.log(variable2); // prints foo
在函數裏聲明變量時,若是須要同時聲明多個變量,這種速記法可以給你節省大量的時間和空間。
常規寫法:
let x; let y; let z = 3;
速記法:
let x, y, z=3;
這可能會有些瑣碎,可是值得一提。當須要用 if 判斷一個變量是否爲真時,賦值運算符有時候能夠省略。
常規寫法:
if (likeJavaScript === true)
速記法:
if (likeJavaScript)
注意:這兩個例子並非徹底相等,只要 likeJavaScript 變量是一個 真值,該表達式就是成立的。
再給出一個例子。若是 "a" 不等於 true,以下:
常規寫法:
let a; if ( a !== true ) { // do something... }
速記法:
let a; if ( !a ) { // do something... }
若是你只想跑原生 JavaScript,不想依賴如 JQuery 或 lodash 這樣的外部庫,那這個小技巧會很是有用。
常規寫法:
for (let i = 0; i < allImgs.length; i++)
速記法:
for (let index in allImgs)
Array.forEach 速記法:
function logArrayElements(element, index, array) { console.log("a[" + index + "] = " + element); } [2, 5, 9].forEach(logArrayElements); // logs: // a[0] = 2 // a[1] = 5 // a[2] = 9
若是咱們不想爲了只是判斷一個變量是 null 或 undefined 就分配一個默認值而寫六行代碼,那麼可使用短路邏輯操做符完成一樣的功能,並且只有一行代碼。
常規寫法:
let dbHost; if (process.env.DB_HOST) { dbHost = process.env.DB_HOST; } else { dbHost = 'localhost'; }
速記法:
const dbHost = process.env.DB_HOST || 'localhost';
你可能隨處可見這種寫法。這是一種比較 fancy 的寫法,省去了後面的一堆零。舉個栗子,1e7 就意味着 1 後面跟着 7 個零。這是十進制基數指數的一種寫法(JavaScript 會按照浮點類型去解釋),和 10,000,000 是相等的。
常規寫法:
for (let i = 0; i < 10000; i++) {}
速記法:
for (let i = 0; i < 1e7; i++) {} // All the below will evaluate to true 1e0 === 1; 1e1 === 10; 1e2 === 100; 1e3 === 1000; 1e4 === 10000; 1e5 === 100000;
在 JavaScript 中定義對象字面量很是簡單。ES6 提供了一個更簡單的定義對象屬性的方法。若是 name 和 key 名字相同,那麼就能夠直接使用以下速記法。
常規寫法:
const obj = { x:x, y:y };
速記法:
const obj = { x, y };
經典的函數寫法易於閱讀,可是一旦將這樣的函數放進回調中就會略顯冗長,並且會形成一些困惑。
常規寫法:
function sayHello(name) { console.log('Hello', name); } setTimeout(function() { console.log('Loaded') }, 2000); list.forEach(function(item) { console.log(item); });
速記法:
sayHello = name => console.log('Hello', name); setTimeout(() => console.log('Loaded'), 2000); list.forEach(item => console.log(item));
這裏須要注意的是:this 值在箭頭函數和常規寫法的函數裏是徹底不一樣的,因此那兩個例子並非嚴格等價的。查看 this article on arrow function syntax獲取更多細節。
咱們常用 return 關鍵字來返回一個函數的結果。僅有一個表達式的箭頭函數會隱性返回函數結果(函數必須省略大括號({})才能省略 return 關鍵字)。
若是要返回多行表達式(好比一個對象字面量),那麼須要用 () 而不是 {} 來包裹函數體。這樣能夠確保代碼做爲一個單獨的表達式被計算返回。
常規寫法:
function calcCircumference(diameter) { return Math.PI * diameter }
速記法:
calcCircumference = diameter => ( Math.PI * diameter; )
你可使用 if 表達式爲函數參數定義默認值。在 ES6 中,你能夠在函數聲明的時候直接定義默認值。
常規寫法:
function volume(l, w, h) { if (w === undefined) w = 3; if (h === undefined) h = 4; return l * w * h; }
速記法:
volume = (l, w = 3, h = 4 ) => (l * w * h); volume(2) //output: 24
你是否是已經厭倦了使用 ' + ' 來將多個變量拼接成一個字符串?難道就沒有更簡單的方式來完成嗎?若是你可使用 ES6 的話,那麼恭喜你,你要作的只是使用反引號和 ${} 來包裹你的變量。
常規寫法:
const welcome = 'You have logged in as ' + first + ' ' + last + '.' const db = 'http://' + host + ':' + port + '/' + database;
速記法:
const welcome = You have logged in as ${first} ${last}; const db = http://${host}:${port}/${database};
若是你正在使用任意一種流行的 web 框架,那麼你頗有可能會使用數組或者對象字面量形式的數據在組件和 API 之間傳遞信息。一旦組件接收到數據對象,你就須要將其展開。
常規寫法:
const observable = require('mobx/observable'); const action = require('mobx/action'); const runInAction = require('mobx/runInAction'); const store = this.props.store; const form = this.props.form; const loading = this.props.loading; const errors = this.props.errors; const entity = this.props.entity;
速記法:
import { observable, action, runInAction } from 'mobx'; const { store, form, loading, errors, entity } = this.props;
你甚至能夠給變量從新分配變量名:
const { store, form, loading, errors, entity:contact } = this.props;
若是你須要在代碼中寫多行字符串,那麼你可能會這樣寫:
常規寫法:
const lorem = 'Lorem ipsum dolor sit amet, consectetur\n\t' + 'adipisicing elit, sed do eiusmod tempor incididunt\n\t' + 'ut labore et dolore magna aliqua. Ut enim ad minim\n\t' + 'veniam, quis nostrud exercitation ullamco laboris\n\t' + 'nisi ut aliquip ex ea commodo consequat. Duis aute\n\t' + 'irure dolor in reprehenderit in voluptate velit esse.\n\t'
可是有一種更簡單的方法:使用反引號。
速記法:
const lorem = Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse.
展開運算符是在 ES6 中引入的,它的多種應用場景使得 JavaScript 代碼使用起來更高效、更有趣。它能夠用來替換某些數組函數。展開運算符寫起來很簡單,就是三個點。
常規寫法:
// joining arrays const odd = [1, 3, 5]; const nums = [2 ,4 , 6].concat(odd); // cloning arrays const arr = [1, 2, 3, 4]; const arr2 = arr.slice()
速記法:
// joining arrays const odd = [1, 3, 5 ]; const nums = [2 ,4 , 6, ...odd]; console.log(nums); // [ 2, 4, 6, 1, 3, 5 ] // cloning arrays const arr = [1, 2, 3, 4]; const arr2 = [...arr];
和 concat()
函數不一樣,你能夠在另外一個數組裏的任意位置插入一個數組。
const odd = [1, 3, 5 ]; const nums = [2, ...odd, 4 , 6];
你也能夠將展開運算符和 ES6 解析賦值結合起來使用:
const { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 }; console.log(a) // 1 console.log(b) // 2 console.log(z) // { c: 3, d: 4 }
若是沒有傳值的話,JavaScript 默認會將函數參數設置爲 undefined。一些其餘的編程語言會拋出警告或錯誤。爲了強制給參數賦值,若是參數沒有定義的話,你可使用 if 表達式拋出錯誤,或者可使用「強制參數速記法」。
常規寫法:
function foo(bar) { if(bar === undefined) { throw new Error('Missing parameter!'); } return bar; }
速記法:
mandatory = () => { throw new Error('Missing parameter!'); } foo = (bar = mandatory()) => { return bar; }
若是你曾經使用原生 JavaScript 寫一個查找函數,你可能會使用 for 循環。在 ES6 中,你可使用數組的一個新方法 find()
。
常規寫法:
const pets = [ { type: 'Dog', name: 'Max'}, { type: 'Cat', name: 'Karl'}, { type: 'Dog', name: 'Tommy'}, ] function findDog(name) { for(let i = 0; i<pets.length; ++i) { if(pets[i].type === 'Dog' && pets[i].name === name) { return pets[i]; } } }
速記法:
pet = pets.find(pet => pet.type ==='Dog' && pet.name === 'Tommy'); console.log(pet); // { type: 'Dog', name: 'Tommy' }
你知道 Foo.bar
能夠寫成 Foo['bar']
吧。一開始,彷佛並無緣由解釋說爲何應該像這樣寫。可是這種寫法可讓你編寫可重用代碼。
考慮下一個驗證函數的簡單例子:
function validate(values) { if(!values.first) return false; if(!values.last) return false; return true; } console.log(validate({first:'Bruce',last:'Wayne'})); // true
這個函數完美的實現了所需的功能。可是,請考慮一個場景:你有許多表單須要驗證,而且不一樣的域有不一樣的驗證規則。那建立一個在運行時被配置的通用驗證函數豈不是更好?
速記法:
// object validation rules const schema = { first: { required:true }, last: { required:true } } // universal validation function const validate = (schema, values) => { for(field in schema) { if(schema[field].required) { if(!values[field]) { return false; } } } return true; } console.log(validate(schema, {first:'Bruce'})); // false console.log(validate(schema, {first:'Bruce',last:'Wayne'})); // true
如今建立了一個能夠在全部的表單裏重用的驗證函數,而沒必要爲每一個表單單獨寫一個特定的驗證函數。
逐位運算符是你在剛學習 JavaScript
時會學到的一個特性,可是若是你不處理二進制的話,基本上是歷來都不會用上的。
可是,雙位運算符有一個很是實用的使用場景:能夠用來代替 Math.floor
。雙位取反運算符的優點在於它執行相同操做的速度更快。你能夠在這裏查看更多關於位運算符的知識。
常規寫法:
Math.floor(4.9) === 4 //true
速記法:
~~4.9 === 4 //true
我確實喜歡這些小技巧,也樂於發現更多的小技巧。若是你有什麼想說的話,就直接留言吧!
譯者:myvin
連接:http://www.zcfy.cc/article/3519
原文:https://www.sitepoint.com/shorthand-javascript-techniques/