【前端见外】20个JS简写小技巧,助你高效敲代码

作者:Amitav Mishra

译者:尴尬风流

原文链接:20 JavaScript Shorthand Techniques that will save your time

个人翻译,转载请注明出处

The shorthand techniques of any programming language help you to write more clean and optimized code and lets you achieve your goal with less coding. Let’s discuss some of the shorthand techniques of JavaScript one by one.

任何一种编程语言的简写小技巧都是为了帮助你写出更简洁、更完善的代码,让你用更少的编码实现你的需求。接下来让我们逐一讨论一下JavaScript中的一些简写小技巧。

1. 声明多个变量

// 常规写法
let x; 
let y = 20; 

// 简写
let x, y = 20;

2. 为多个变量赋值

We can assign values to multiple variables in one line with array destructuring.

我们可以使用数组解构赋值,仅用一行代码实现为多个变量赋值。

// 常规写法 
let a, b, c; 
a = 5; 
b = 8; 
c = 12;
 
// 简写
let [a, b, c] = [5, 8, 12];

3. 恰当使用三元运算符

We can save 5 lines of code here with ternary (conditional) operator.

我们可以在这里用三元运算符(也称条件运算符)节省5行代码。

// 常规写法
let marks = 26; 
let result; 
if(marks >= 30){
 result = 'Pass'; 
}else{ 
 result = 'Fail'; 
} 
// 简写
let result = marks >= 30 ? 'Pass' : 'Fail';

4. 指定默认值

We can use OR(||) short circuit evaluation to assign a default value to a variable in case the expected value found falsy.

我们可以使用「OR ( || ) 短路求值」的逻辑,来给定一个默认值。当 || 我们的期望值是一个「falsy」值的时候,整个表达式的值便会取到我们给定的默认值。

// 常规写法
let imagePath; 
let path = getImagePath(); 
if(path !== null && path !== undefined && path !== '') { 
  imagePath = path; 
} else { 
  imagePath = 'default.jpg'; 
} 

// 简写
let imagePath = getImagePath() || 'default.jpg';

5. AND(&&)短路求值

If you are calling a function only if a variable is true, then you can use AND(&&) short circuit as an alternative for this.

如果你只在一个变量为真的情况下才调用某个函数,那么你可以用「AND(&&)短路求值」的逻辑来代替。

// 常规写法
if (isLoggedin) {
 goToHomepage(); 
} 

// 简写
isLoggedin && goToHomepage();

The AND(&&) short circuit shorthand is more useful in React when you want to conditionally render a component. For example:

在React中,当你想有条件地渲染某个组件时,可以尝试使用AND(&&)这种简写方式。例如下面这个例子👇

<div> { this.state.isLoading && <Loading /> } </div>

译者注:表达式的值为0这种特殊的falsy值时,请谨慎考虑使用

6. 交换两个变量的值

To swap two variables, we often use a third variable. We can swap two variables easily with array destructuring assignment.

当我们想交换两个变量的值时,经常会采取引入第三个变量的方法。其实我们可以通过数组解构赋值轻松地交换两个变量。

let x = 'Hello', y = 55; 

// 常规写法,引入第三个变量
const temp = x; 
x = y; 
y = temp; 

// 简写,使用数组解构赋值
[x, y] = [y, x];

7. 善用箭头函数

// 常规写法
function add(num1, num2) { 
   return num1 + num2; 
} 

// 简写
const add = (num1, num2) => num1 + num2;

参考「箭头函数」

8. 模板字符串

We normally use + operator to concatenate string values with variables. With ES6 template literals we can do it in a more simple way.

我们通常使用+运算符来连接字符串和其他类型的变量。有了ES6模板字符串,我们可以用更简单的方式来组合字符串。

// 常规写法 
console.log('You got a missed call from ' + number + ' at ' + time); 

// 简写
console.log(`You got a missed call from ${number} at ${time}`);

9. 多行字符串

For multiline string we normally use + operator with a new line escape sequence (\n). We can do it in an easier way by using backticks (`)

对于多行字符串,我们通常使用+操作符和一个新的换行符(\n)拼接实现。其实我们可以通过使用反引号(`)来更简单地实现。

// 常规写法
console.log('JavaScript, often abbreviated as JS, is a\n' +             
            'programming language that conforms to the \n' + 
                        'ECMAScript specification. JavaScript is high-level,\n' + 
                        'often just-in-time compiled, and multi-paradigm.' ); 

// 简写
console.log(`JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled, and multi-paradigm.`);

10. 多条件检查

For multiple value matching, we can put all values in array and use indexOf() or includes() method.

对于多值匹配,我们可以把所有的值放在数组中,使用数组提供的indexOf()includes()方法来简写。

// 常规写法
if (value === 1 || value === 'one' || value === 2 || value === 'two') { 
     // 执行一些代码
} 

// 简写1
if ([1, 'one', 2, 'two'].indexOf(value) >= 0) { 
    // 执行一些代码 
}
// 简写2
if ([1, 'one', 2, 'two'].includes(value)) { 
    // 执行一些代码 
}

11. 对象属性分配

If the variable name and object key name is same then we can just mention variable name in object literals instead of both key and value. JavaScript will automatically set the key same as variable name and assign the value as variable value.

如果变量名和对象的属性名相同,那么我们可以在对象的中只写变量名,而不用同时写出属性名和属性值(变量的值)。JavaScript会自动将属性名设置为与变量名相同,并将属性值分配为变量值。

let firstname = 'Amitav'; 
let lastname = 'Mishra'; 

// 常规写法 
let obj = {firstname: firstname, lastname: lastname}; 

// 简写 
let obj = {firstname, lastname};

12. 字符串(String)转为数字(Number)

There are built in methods like parseInt and parseFloat available to convert a string to number. We can also do this by simply providing a unary operator (+) in front of string value.

有一些内置方法,如 parseIntparseFloat ,可以将字符串转换为数字。我们也可以通过简单地在字符串值前面提供一个一元运算符 + 来实现。

// 常规写法
let total = parseInt('453'); 
let average = parseFloat('42.6'); 

// 简写
let total = +'453'; 
let average = +'42.6';

13. 多次重复一个字符串

To repeat a string for a specified number of time you can use a for loop. But using the repeat() method we can do it in a single line.

要将一个字符串重复指定的次数,你可以使用for循环。但使用repeat()方法,我们可以在一行中完成。

// 常规写法
let str = ''; 
for(let i = 0; i < 5; i ++) { 
  str += 'Hello '; 
} 
console.log(str); // Hello Hello Hello Hello Hello 

// 简写
'Hello '.repeat(5);

Tip: Want to apologize to someone by sending 100 times “sorry”? Try it with repeat() method. If you want to repeat each string in a new line, then add \n to the string.

想对某人说100次对不起?试试 repeat() 方法吧。如果你希望每一个字符串占一行,那么就在字符串结尾添加换行符( \n)。

// 想跟你说100声抱歉!
'sorry\n'.repeat(100);

14. 幂的力量!

We can use Math.pow() method to find the power of a number. There is a shorter syntax to do it with double asterik (**).

我们可以使用 Math.pow() 方法来求一个数字的幂。有一个更简洁的语法,那就是双星号(**)。

// 常规写法
const power = Math.pow(4, 3); // 64 

// 简写
const power = 4**3; // 64

15. 双NOT位运算符(~~)?

The double NOT bitwise operator is a substitute for Math.floor() method.

双NOT位运算符(~~)是 Math.floor() 方法的替代品。

// 常规写法
const floor = Math.floor(6.8); // 6 

// 简写
const floor = ~~6.8; // 6

Improvement from comment by Caleb:
The double NOT bitwise operator approach only works for 32 bit integers i.e (231)-1 = 2147483647. So for any number higher than 2147483647, bitwise operator (~~) will give wrong results, so recommended to use Math.floor() in such case.

感谢Caleb的提醒:
双NOT位运算符方法
只适用于32位整数,即(231)-1=2147483647。所以对于任何大于2147483647的数字,位运算符(~~)会给出错误的结果,所以建议在这种情况下使用Math.floor()。

16. 找出数组中的最大最小值

We can use for loop to loop through each value of array and find the max or min value. We can also use the Array.reduce() method to find the max and min number in array.

我们可以使用for循环来遍历数组,找到最大值或最小值。也可以使用Array.reduce()方法来寻找数组中的最大和最小值。

But using spread operator we can do it in a single line.

但是使用展开操作符(...)我们可以,我们可以用一行代码就实现这个需求。

// 简写
const arr = [2, 8, 15, 4]; 
Math.max(...arr);  // 最大值 15 
Math.min(...arr);  // 最小值 2

17. 关于For循环

To loop through an array we normally use the traditional for loop. We can make use of the for...of loop to iterate through arrays. To access the index of each value we can use for...in loop.

要遍历一个数组,我们通常使用传统的 for 循环。我们可以利用 for...of 的方式来遍历一个数组。如果要访问数组每个值的索引,我们可以使用 for...in 循环。

let arr = [10, 20, 30, 40]; 

// 常规写法,for循环
for (let i = 0; i < arr.length; i++) { 
  console.log(arr[i]); 
} 

// 简写

// for...of循环
for (const val of arr) { 
  console.log(val); 
} 

// for...in循环
for (const index in arr) { 
  console.log(`index: ${index} and value: ${arr[index]}`); 
}

We can also loop through object properties using for...in loop.

我们还可以使用 for...in 循环来遍历对象的属性。

let obj = {x: 20, y: 50}; 
for (const key in obj) { 
  console.log(obj[key]); 
}

参考:JavaScript中遍历对象和数组的几种不同的方式

18. 合并数组

let arr1 = [20, 30]; 

// 常规写法
let arr2 = arr1.concat([60, 80]); 
// [20, 30, 60, 80] 

// 简写
let arr2 = [...arr1, 60, 80]; 
// [20, 30, 60, 80]

19. 多层次对象的深拷贝

To deep clone a multi-level object, we can iterate through each property and check if the current property contains an object. If yes, then do a recursive call to the same function by passing the current property value (i.e. the nested object).

要对一个多层次的对象实现深拷贝,我们可以遍历其每个属性,检查当前属性是否包含一个对象。如果是,则递归调用同一个函数,并将当前属性值(即嵌套对象)作为函数的参数传递进去。

We can also do it by using JSON.stringify() and JSON.parse() if our object doesn't contains functions, undefined, NaN or Date as values.

如果我们的对象不包含函数undefinedNaNDate等值,我们也可以使用 JSON.stringify()JSON.parse() 来实现。

If we have single level object i.e no nested object present, then we can deep clone using spread operator also.

如果我们的对象是单层对象,即没有嵌套对象,那么我们也可以使用展开操作符(...)进行深拷贝。

let obj = {x: 20, y: {z: 30}}; 

// 常规写法,递归
const makeDeepClone = (obj) => { 
  let newObject = {}; 
  Object.keys(obj).map(key => { 
    if(typeof obj[key] === 'object'){ 
      newObject[key] = makeDeepClone(obj[key]); 
    } else { 
      newObject[key] = obj[key]; 
    } 
  }); 
 return newObject; 
} 
const cloneObj = makeDeepClone(obj); 

// 特殊情况下(对象中属性值没有函数、undefined或NaN的情况下)的简写
const cloneObj = JSON.parse(JSON.stringify(obj));

// 单层对象(无嵌套对象)情况下的简写
let obj = {x: 20, y: 'hello'};
const cloneObj = {...obj};

Improvement from comment:
The shorthand technique (JSON.parse(JSON.stringify(obj))) doesn’t work if your object property contains function, undefined or NaN as value. Because when you JSON.stringify the object, the property containing function, undefined or NaN as value gets removed from the object.
So use JSON.parse(JSON.stringify(obj)) when your object contains only strings and numbers.

感谢评论区中的提醒:
如果你的对象属性中包含函数undefinedNaN作为属性值时,**JSON.parse(JSON.stringify(obj)) **这种简写将会失效。因为当你对对象进行 JSON.stringify 时,包含函数、undefined或NaN作为值的属性会从对象中被删除。
所以当你的对象只包含字符串和数字时,才可以使用 JSON.parse(JSON.stringify(obj))

参考:JSON.parse() 和 JSON.stringify()

20. 获取字符串中的某个字符

let str = 'jscurious.com'; 

// 常规写法
str.charAt(2); // c 

// 简写
str[2]; // c

Some of these shorthand techniques may not seems relevant to use in project but it’s not bad to know some extra techniques.
这些简写小技巧中的一些似乎不太适合在项目中使用,但知道总比不知道强。

Happy coding!

好编码,编好码,编码好!
**

【附】专有名词总结:

中文 英文
简写技巧 shorthand techniques
赋值 assign value
数组解构赋值 array destructuring assignment
条件操作符 conditional operator
展开操作符 spread operater
深拷贝 deep clone
期望值 expected value
多值匹配 multiple value matching
内置方法 built in method
递归调用 recursive call
嵌套对象 nested object
模板字符串(模板字面量) template literals
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容