js小技巧--摘录1
原文地址https://github.com/loverajoel/jstips
1、数组中插入元素
a.尾部追加
var arr = [1,2,3,4,5]; var arr2 = []; arr.push(6); arr[arr.length] = 6; arr2 = arr.concat([6]);
//快慢排序
1. arr[arr.length] = 6; // 平均42 345 449 ops/sec 2. arr.push(6); // 慢34.66% 3. arr2 = arr.concat([6]); // 慢85.79%
b.头部追加
ar arr = [1,2,3,4,5]; arr.unshift(0); [0].concat(arr);
//最快的为 1. [0].concat(arr); // 平均4 972 622 ops/sec 2. arr.unshift(0); // 慢64.70%
c.数组中间插入元素
var items = ['one', 'two', 'three', 'four']; items.splice(items.length / 2, 0, 'hello');
2、if嵌套语句的优化
if (color) { if (color === 'black') { printBlackBackground(); } else if (color === 'red') { printRedBackground(); } else if (color === 'blue') { printBlueBackground(); } else if (color === 'green') { printGreenBackground(); } else { printYellowBackground(); } } //可以改写为 var colorObj = { 'black': printBlackBackground, 'red': printRedBackground, 'blue': printBlueBackground, 'green': printGreenBackground, 'yellow': printYellowBackground }; if (color in colorObj) { colorObj[color](); }
3、sort排序含音节字符的字符串
Javascript有一个原生方法sort可以排列数组。一次简单的array.sort()
将每一个数组元素视为字符串并按照字母表排列。你也可以提供自定义排列方法
['Shanghai', 'New York', 'Mumbai', 'Buenos Aires'].sort(); // ["Buenos Aires", "Mumbai", "New York", "Shanghai"] //下面非ASCLL元素失效,sort只在英文下生效 // 西班牙语 ['único','árbol', 'cosas', 'fútbol'].sort(); // ["cosas", "fútbol", "árbol", "único"] // bad order // 德语 ['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(); // ["Wann", "Woche", "wäre", "wöchentlich"] // bad order
处理办法:由ECMAScript国际化API提供的localeCompare和Intl.Collator。
['único','árbol', 'cosas', 'fútbol'].sort(function (a, b) { return a.localeCompare(b); }); // ["árbol", "cosas", "fútbol", "único"] ['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(function (a, b) { return a.localeCompare(b); }); // ["Wann", "wäre", "Woche", "wöchentlich"] ['único','árbol', 'cosas', 'fútbol'].sort(Intl.Collator().compare); // ["árbol", "cosas", "fútbol", "único"] ['Woche', 'wöchentlich', 'wäre', 'Wann'].sort(Intl.Collator().compare); // ["Wann", "wäre", "Woche", "wöchentlich"]
4、使用严格模式
程序员喜欢电脑帮我们做一些无聊的工作,喜欢它自动的检查我们工作上的错误。这就是”use strict”帮我们做的,它把我们的错误转变为了JavaScript错误。
// 全脚本严格模式 "use strict"; var v = "Hi! I'm a strict mode script!"; //或者 function f() { // 方法级严格模式 'use strict'; function nested() { return "And so am I!"; } return "Hi! I'm a strict mode function! " + nested(); } function f2() { return "I'm not strict."; }
通过在JavaScript文件或方法内引入此指令,使JavaScript引擎运行在严格模式下,这直接禁止了许多大项目中不受欢迎的操作。另外,严格模式也改变了以下行为:
- 只有被”var”声明过的变量才可以引用
- 试图写只读变量时将会报错
- 只能通过”new”关键字调用构造方法
- “this”不再隐式的指向全局变量
- 对eval()有更严格的限制
- 防止你使用预保留关键字命名变量
严格模式对于新项目来说是很棒的,但对于一些并没有使用它的老项目来说,引入它也是很有挑战性的。如果你把所有js文件都连接到一个大文件中的话,可能导致所有文件都运行在严格模式下,这可能也会有一些问题。
它不是一个声明,而是一个表达式,被低版本的JavaScript忽略。 严格模式的支持情况:
- Internet Explorer 10+
- Firefox 4+
- Chrome 13+
- Safari 5.1+
- Opera 12+
5、将node list转为数组
querySelectorAll
方法返回一个类数组对象称为node list。这些数据结构被称为“类数组
const nodelist = document.querySelectorAll('div'); const nodelistToArray = Array.apply(null, nodelist); //或者 const nodelistToArray = Array.prototype.slice.call(nodelist);
const nodelist
ToArray= [...document.querySelectorAll('div')]; // 返回一个真正的数组
//之后 ..
nodelistToArray.forEach(...);
nodelistToArray.map(...);
nodelistToArray.slice(...);
6、检查对象是否存在某属性
var myObject = { name: '@tips_js' }; if (myObject.name) { ... } //这样可以 //同时用hasOwnProperty和in操作符可以区分属性是继承的还是自身的 var myObject = { name: '@tips_js' }; myObject.hasOwnProperty('name'); // true 'name' in myObject; // true myObject.hasOwnProperty('valueOf'); // false, valueOf 继承自原型链 'valueOf' in myObject; // true
7、contains功能
位操作符 ~, “按位操作符操作数字的二进制形式,但是返回值依然是标准的JavaScript数值。”
它将-1
转换为0
,而0
在javascript为false
,所以:
var someText = 'text'; !!~someText.indexOf('tex'); // someText contains "tex" - true !~someText.indexOf('tex'); // someText NOT contains "tex" - false ~someText.indexOf('asd'); // someText doesn't contain "asd" - false ~someText.indexOf('ext'); // someText contains "ext" - true //在ES6中提供了includes() 方法供我们判断一个字符串是否包含了另一个字符串: 'something'.includes('thing'); // true //在ECMAScript 2016 (ES7)甚至可能将其应用于数组,像indexOf一样: !!~[1, 2, 3].indexOf(1); // true [1, 2, 3].includes(1); // true
8、快速但是危险的取整方法(~~)
一个按位非操作符~
首先将输入input
截取为32位,然后将其转换为-(input+1)
。因此双按位非操作符将输入转换为-(-(input + 1)+1)
,使其成为一个趋向于0取整的好工具。对于数字的输入,它很像Math.trunc()
。失败时返回0
,这可能在解决Math.trunc()
转换错误返回NaN
时是一个很好的替代。
console.log(~~47.11) // -> 47 console.log(~~1.9999) // -> 1 console.log(~~3) // -> 3 console.log(~~-3.66) // -> -3
当处理大数时
因为~
首先将数组转换为32位,~~
的结果伪值在 ±2.15*10^12左右。如果你没有明确的检查输入值的范围,当转换的值最终与原始值有很大差距时,用户就可能触发未知的行为:
a = 2147483647.123 // 比32位最大正数,再多一点 console.log(~~a) // -> 2147483647 (ok) a += 10000 // -> 2147493647.123 (ok) console.log(~~a) // -> -2147483648 (huh?)
9.安全拼接字符串
var one = 1; var two = 2; var three = '3'; var result = ''.concat(one, two, three); //"123"
10、对数组进行洗牌
这段代码运用了优秀的Fisher-Yates Shuffling算法对数组进行洗牌
const shuffle = arr => { for (let i = arr.length - 1; i > 0; i--) { let j = ~~(Math.random() * (i + 1)); [arr[i],arr[j]] = [arr[j],arr[i]] } return arr; } var a = [1, 2, 3, 4, 5, 6, 7, 8]; var b = shuffle(a); console.log(b); // [2, 7, 8, 6, 5, 3, 1, 4]
11、清空数组的两种方法
// 定义一个数组 var list = [1, 2, 3, 4]; //清空数组 list = []; //或者 list.length = 0;
-
list = []
将一个新的数组的引用赋值给变量,其他引用并不受影响。 这意味着以前数组的内容被引用的话将依旧存在于内存中,这将导致内存泄漏。 -
list.length = 0
删除数组里的所有内容,也将影响到其他引用。
然而,如果你复制了一个数组(A 和 Copy-A),如果你用list.length = 0
清空了它的内容,复制的数组也会清空它的内容。
var foo = [1,2,3]; var bar = [1,2,3]; var foo2 = foo; var bar2 = bar; foo = []; bar.length = 0; console.log(foo, bar, foo2, bar2); //[] [] [1, 2, 3] []