有没有一个好的JS速记参考指南?

31

我希望在我的日常编程习惯中运用缩写技巧,并且能够在压缩代码中看到它们时也能读懂。

有人知道一个参考页面或文档,概述这些技术吗?

编辑:我之前提到了缩小文件大小和高效JS输入技术,现在我明白缩小文件大小和高效JS输入技术是两个几乎完全不同的概念。

5个回答

44

更新:加入了ECMAScript 2015(ES6)的好处,详情请见底部。

最常用的条件语句简写方式有:

a = a || b     // if a is falsy use b as default
a || (a = b)   // another version of assigning a default value
a = b ? c : d  // if b then c else d
a != null      // same as: (a !== null && a !== undefined) , but `a` has to be defined

使用对象字面量表示法创建对象和数组:

obj = {
   prop1: 5,
   prop2: function () { ... },
   ...
}
arr = [1, 2, 3, "four", ...]

a = {}     // instead of new Object()
b = []     // instead of new Array()
c = /.../  // instead of new RegExp()

内置类型(数字,字符串,日期,布尔值)

// Increment/Decrement/Multiply/Divide
a += 5  // same as: a = a + 5
a++     // same as: a = a + 1

// Number and Date
a = 15e4        // 150000
a = ~~b         // Math.floor(b) if b is always positive
a = b**3        // b * b * b
a = +new Date   // new Date().getTime()
a = Date.now()  // modern, preferred shorthand 

// toString, toNumber, toBoolean
a = +"5"        // a will be the number five (toNumber)
a = "" + 5 + 6  // "56" (toString)
a = !!"exists"  // true (toBoolean)

变量声明:

var a, b, c // instead of var a; var b; var c;

字符串中特定位置的字符:

"some text"[1] // instead of "some text".charAt(1);

ECMAScript 2015 (ES6) 标准缩写

这些是相对较新的补充,因此不要指望广泛支持所有浏览器。 它们可能得到现代环境(例如:较新的 node.js)或通过转译器的支持。当然,“旧”版本仍将继续工作。

箭头函数

a.map(s => s.length)                    // new
a.map(function(s) { return s.length })  // old

Rest参数

// new 
function(a, b, ...args) {
  // ... use args as an array
}

// old
function f(a, b){
  var args = Array.prototype.slice.call(arguments, f.length)
  // ... use args as an array
}

默认参数值

function f(a, opts={}) { ... }                   // new
function f(a, opts) { opts = opts || {}; ... }   // old

解构赋值

var bag = [1, 2, 3]
var [a, b, c] = bag                     // new  
var a = bag[0], b = bag[1], c = bag[2]  // old  

对象字面量中的方法定义

// new                  |        // old
var obj = {             |        var obj = {
    method() { ... }    |            method: function() { ... }
};                      |        };

对象字面量内的计算属性名

// new                               |      // old
var obj = {                          |      var obj = { 
    key1: 1,                         |          key1: 5  
    ['key' + 2]() { return 42 }      |      };
};                                   |      obj['key' + 2] = function () { return 42 } 

额外福利:内置对象的新方法

// convert from array-like to real array
Array.from(document.querySelectorAll('*'))                   // new
Array.prototype.slice.call(document.querySelectorAll('*'))   // old

'crazy'.includes('az')         // new
'crazy'.indexOf('az') != -1    // old

'crazy'.startsWith('cr')       // new (there's also endsWith)
'crazy'.indexOf('az') == 0     // old

'*'.repeat(n)                  // new
Array(n+1).join('*')           // old 

奖励2:箭头函数也使得捕获self = this变得不必要

// new (notice the arrow)
function Timer(){
    this.state = 0;
    setInterval(() => this.state++, 1000); // `this` properly refers to our timer
}

// old
function Timer() {
    var self = this; // needed to save a reference to capture `this`
    self.state = 0;
    setInterval(function () { self.state++ }, 1000); // used captured value in functions
}

类型的最终备注

要小心使用隐式和隐藏的类型转换和四舍五入,因为它可能会导致代码不够易读,并且其中一些不受现代JavaScript风格指南的欢迎。 但即使是那些更加晦涩的内容也有助于理解他人的代码、阅读精简的代码。


6
x && (doWhentrue); << conditional. performance wise same as if(x) do; - Muhammad Umer
所以,经过所有这些简写,Math.pow(x, 2)仍然是求x的平方的最短方式吗? - Samie Bencherif
目前 x*x 是最短的方式 :) 然而,现代浏览器正在实现指数运算符(ES7):https://github.com/rwaldron/exponentiation-operator 因此,您将能够执行 x ** 2,当然对于其他指数更有用。 - gblazex
请注意!使用箭头函数的时候需要注意,它们内部不会有thisfunction () {}() => {}是不同的。 - Jay Edwards

17

如果你将JavaScript版本定义为1.5及以后的版本,那么你还可以了解以下内容:


表达式闭包:

JavaScript 1.7及之前的版本:

var square = function(x) { return x * x; }

JavaScript 1.8添加了一种简写的Lambda符号表示法,用于使用表达式闭包编写简单函数:

var square = function(x) x * x;

reduce()方法:

JavaScript 1.8版本还向数组引入了reduce() 方法:

var total = [0, 1, 2, 3].reduce(function(a, b){ return a + b; });  
// total == 6 

解构赋值:

在 JavaScript 1.7 中,你可以使用解构赋值,例如,可以避免使用临时变量来交换值:

var a = 1;  
var b = 3;  

[a, b] = [b, a]; 

数组推导和 filter() 方法:

数组推导 是在 JavaScript 1.7 版本引入的,它可以简化以下代码:

var numbers = [1, 2, 3, 21, 22, 30];  
var evens = [];

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    evens.push(numbers[i]);
  }
}

转换成这样:

var numbers = [1, 2, 3, 21, 22, 30];
var evens = [i for each(i in numbers) if (i % 2 === 0)];

或者使用 JavaScript 1.6 中引入的数组方法filter()

var numbers = [1, 2, 3, 21, 22, 30];
var evens = numbers.filter(function(i) { return i % 2 === 0; });  

我不认为任何缩小器会做这些... :) - gblazex
@galambalazs:不,我也不这么认为。如果缩小器这样做是不正确的,因为这样的转换会使代码在支持JavaScript 1.5版本的引擎中不兼容...尽管如此,在后续版本中仍有一些选项可以缩短代码,可能更多地用于提高可读性而不是缩小。 - Daniel Vassallo
@galambalazs:我没有那样解释这个问题 :) ... OP问道:“我想在我的常规编码习惯中加入任何速记技巧...” - Daniel Vassallo
@galambalazs:它们可能暂时对于浏览器脚本编写并不是很有用,但是例如Spider Monkey支持JavaScript 1.8版本,而Rhino支持1.7版本。 - Daniel Vassallo
1
当我为每个 bla bla 运行代码时,我得到了“SyntaxError: Unexpected token for”的错误。 - Muhammad Umer
显示剩余4条评论

3
您正在寻找 JavaScript 语言的习语。

浏览一下JavaScript 1.6+ 的新特性确实很有趣,但由于缺乏主流支持,您将无法在实际使用中使用语言功能(例如列表推导式或yield关键字)。然而,如果您没有接触过 Lisp 或 Scheme,了解新的标准库函数是值得的。许多典型的函数式编程片段,如mapreducefilter都很好知道,并经常出现在像 jQuery 这样的 JavaScript 库中;另一个有用的函数是bind(在一定程度上是 jQuery 的proxy),在指定方法作为回调时非常有帮助。


1

获取数组的最后一个值

这并不是一种速记方式,而更像是大多数人使用的技术的较短替代技巧。

当我需要获取数组的最后一个值时,我通常使用以下技巧:

var str = 'Example string you actually only need the last word of FooBar';
var lastWord = str.split(' ').slice(-1)[0];
< p > .slice(-1)[0] 的一部分是速记技术。与我见过的几乎所有人使用的方法相比,这更短:

var str = 'Example string you actually only need the last word of FooBar';
var lastWord = str.split(' ');
    lastWord = lastWord[lastWord.length-1];

测试这个速记法的相对计算速度

为了测试这个速记法,我进行了以下操作:

var str = 'Example string you actually only need the last word of FooBar';
var start = +new Date();
for (var i=0;i<1000000;i++) {var x=str.split(' ').slice(-1)[0];}
console.log('The first script took',+new Date() - start,'milliseconds');

然后单独运行(以防止可能的同步运行):

var start2 = +new Date();
for (var j=0;j<1000000;j++) {var x=str.split(' ');x=x[x.length-1];}
console.log('The second script took',+new Date() - start,'milliseconds');

结果如下:
The first script took 2231 milliseconds
The second script took 8565 milliseconds

简化调试

大多数浏览器都支持为每个具有ID的元素隐藏全局变量。因此,如果我需要调试某些东西,我通常只需向该元素添加一个简单的ID,然后使用控制台通过全局变量访问它。您可以自己检查一下:只需在此处打开控制台,键入footer并按Enter。它很可能会返回<div id="footer">,除非您的浏览器很少见并且不支持这种方式(我没有找到任何一款)。

如果全局变量已被其他变量占用,我通常使用可怕的document.all['idName']document.all.idName。我当然知道这已经过时了,并且我不在任何实际脚本中使用它,但当我不想真正输入完整的document.getElementById('idName')时,我还是会使用它,因为大多数浏览器都支持,是的,我确实很懒。

结论:使用这种简写没有任何缺点。


1

你让我的一天变得美好!这个要点很不错,我刚刚学到了很多东西 ;) - Latsuj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接