0. 向下取整最快方式
向下取整有很多方法, Math.floor, parseInt都可以, 不过两个非(~)运算符来取整是最方便的, 而且逻辑运算很快.
还可以用~~再加1来向上取整.
~~3.14
> 3
~~Math.PI
> 3
~~Math.E
> 2
~~12.98
> 12
var b= 2.33 | 0 ---b=2
var c= 2.33 >> 0 ----c=2
1. 转数值类型最快方式
字符串转数字类型也有很多方式, parseFloat, Number(), 但官方推荐直接用一个加号(+)运算符, 是最快最简洁的.
+ new Date()
> 1559785422952
+'123'
> 123
+ {}
> NaN
2. 四舍五入
这个不算奇淫技巧了, 因为本身就与Math.round和toFixed(), 以及toPrecision来实现.
+Math.E.toFixed(0)
> 3
+Math.E.toFixed(1)
> 2.7
+Math.E.toFixed(2)
> 2.72
3. ===比==快
==和!=操作符会在需要的情况下自动转换数据类型。但===和!==不会,它们会同时比较值和数据类型, 避免了多余的计算,这也使得它们要比==和!=快。
现在人很少利用==来做类型转换了, JS也有往强类型发展的趋势.
4. 最安全的交换变量
如何不借助第三个变量(容器)交换2个变量a和b的内容呢? 最安全且最快的办法是利用异或门(^)来进行:
let a = 12;
let b = 123;
a = a ^ b;
b = a ^ b;
a = a ^ b;
a;
> 123
b;
> 12
可能有老师教用加法(+)来取代异或, 加法不仅慢而且容易产生溢出, 不安全, 所以不提倡加法交换. 异或或者同或才能实现在2个容器的情况下保证数据不丢失.
如果借助第三方存储空间老交换变量, 虽然性能不是最优, 看上去会比较直观一些, 最直观的写法是通过数组解构:
[a, b] = [b, a];
// 这样就无需注释了
5. 获取指定范围内均匀分布的随机数
let x = Math.random() * (max - min) + min;
如果需要正态分布, 可以在此基础改造...
6. 最快生成[1,2,3, .... ,n] 的列表
利用列表的下标index来生成数是非常快的.
Array(10).fill(true).map((x,i)=>i+1);
> (10) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
还可以看出, 快速构建一个长度为n的列表可以使用Array(n).fill(1);
同理, 构造奇数偶数序列也可以通过这种方式, 还有很多基于自然数的有规律序列都可以这样生成.
7. 打乱列表
利用sort方法快速排序的时候引入一个随机量..嘿嘿
const list = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
list.sort(()=>Math.random()-0.5)
> (8) [120, 122205, 458, 400, 5, -215, -85411, 228]
8. 列表聚合
Array.prototype.reduce是一个对列表进行摘要的算法(输入多个元素, 输出一个值), 比如数值列表求和:
list.reduce((sum, curr)=>sum+curr,0)
9. 列表遍历取代循环语句
函数式编程中可以利用Array的forEach, map, filter, some, every, find来取代传统的for循环, while循环, 不仅更优雅, 而且提升了一定效率, 具体方式可以参考我之前的文章.
10. 最快构造一个循环链表
每次执行一下list.push(list.shift());然后访问list[0], 无需额外代码, 最直接实现循环链表, 帅!
const list = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
list.push(list.shift());
list[0];
> 458
list.push(list.shift());
list[0];
> 120
list.push(list.shift());
list[0];
> -215
重此以后再也不用判断index到头然后改成0了...
11. 字典的键值对取代switch语句
使用字典取代switch和if else语句也是函数式编程的理念之一.
const day = 'Monday';
({
'Monday':()=>{},
'Wednesday':()=>{},
'Friday':()=>{},
'default':()=>{},
})[ day || 'default' ];
超级实用的健康提示!
12. null,undefined,''
let exp=null; exp=undefined; exp="" 一般只需要用 (!exp) 来判断就可以了
13. JS自以为是的Truthy和Falsy
Truthy (真值)指的是在 布尔值 上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为 falsy (即除了 false,0,"",null,undefined 和 NaN 外)。
JS 中的真值示例如下(将被转换为 true,if 后的代码段将被执行):
if (true)
if ({})
if ([])
if (42)
if ("foo")
if (new Date())
if (-42)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值.
在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion )将值转换为布尔值,比如:在条件语句或者循环语句中
JavaScript中falsy值的例子 (通过 if 代码段将falsy值转换为false):
if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (document.all)
然而我不推荐在生产环境下利用逻辑或和逻辑与来判断truthy和falsy, 因为有时候人认为0是有意义的, 而[]是无意义的, 然而在JS里面, 对0和[]的真值判断是相反的.
14. 利用Set对列表去重
[...new Set([42, 'foo', 42, 'foo', true, true])]
> (3) [42, "foo", true]
15. 自定义toJSON方法(fuck原型)
将标准库的一些构造函数给他们赋予toJSON方法, 这样在JSON.stringify的时候就可以生成定制的json,而不是空的了, 这在http传输的时候会非常有用.
Date.prototype.toJSON = function () {
return this.getTime();
}
Function.prototype.toJSON = function () {
return this.toString();
}
RegExp.prototype.toJSON = function () {
return this.toString();
}
JSON.stringify([new Date(),Array, /.*/]);
> "[1559795757062,"function Array() { [native code] }","/.*/"]"
16. 使用getter和setter实现dom数据绑定
传送门: getter, setter
17. 使用模板字符串实现html和css的模板引擎
const unfold = list => list.map(li => `
// 导出模块
module.exports = data => `
上面的node模块就是HTML的模板引擎, 可以完美的替代市面上的各种产品包括ejs,php,jsp以及Vue脚手架等, 最开心的是不用去学习他们的语法, 利用ES6的模板字符串就可以定制自己喜欢的语法.
同理, CSS和其他类型的标记语言, 都可以通过这种方式而不需要依赖于第三方包.
18. 串行执行动态promise集
并行执行promise很简单,只要使用Promise.all方法就行了,但有没有Promise.sequential呢,也就是串行执行,其实是可以的,要利用Array.prototype.reduce方法来构造一个promise链:
taskList.reduce(async (chain, next) => {
await chain;
return next();
}, Promise.resolve());
19. 使用!!将变量转换成布尔类型
function Account(cash) {
this.cash = cash;
this.hasMoney = !!cash;
}
var account = new Account(100.50);
console.log(account.cash); // 100.50
console.log(account.hasMoney); // true
var emptyAccount = new Account(0);
console.log(emptyAccount.cash); // 0
console.log(emptyAccount.hasMoney); // false
20. 短路条件
if (conected) {
login();
}
//在这两个变量之间使用&&(AND运算符)来缩短代码
conected && login();
//你也可以用这种方法来检查对象中是否存在某些属性或函数。类似于以下代码:
user && user.login();
21. 使用||设置默认值
function User(name, age) {
this.name = name || "Oliver Queen";
this.age = age || 27;
}
var user1 = new User();
console.log(user1.name); // Oliver Queen
console.log(user1.age); // 27
var user2 = new User("Barry Allen", 25);
console.log(user2.name); // Barry Allen
console.log(user2.age); // 25
22. 在循环中缓存array.length
//这个技巧非常简单,并且在循环处理大数组时能够避免对性能造成巨大的影响。基本上几乎每个人都是这样使用for来循环遍历一个数组的:
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
//如果你使用较小的数组,那还好,但是如果处理大数组,则此代码将在每个循环里重复计算数组的大小,这会产生一定的延迟。为了避免这种情况,你可以在变量中缓存array.length,以便在循环中每次都使用缓存来代替array.length:
var length = array.length;
for (var i = 0; i < length; i++) {
console.log(array[i]);
}
//为了更简洁,可以这么写:
for (var i = 0, length = array.length; i < length; i++) {
console.log(array[i]);
}
23. 检测对象中的属性
//当你需要检查某些属性是否存在,避免运行未定义的函数或属性时,这个技巧非常有用。如果你打算编写跨浏览器代码,你也可能会用到这个技术。例如,我们假设你需要编写与旧版Internet Explorer 6兼容的代码,并且想要使用document.querySelector()来通过ID获取某些元素。 但是,在现代浏览器中,这个函数不存在。所以,要检查这个函数是否存在,你可以使用in运算符。看下这个例子:
if ('querySelector' in document) {
document.querySelector("#id");
} else {
document.getElementById("id");
}
24. 获取数组的最后一个元素
//Array.prototype.slice(begin,end)可以用来裁剪数组。但是如果没有设置结束参数end的值的话,该函数会自动将end设置为数组长度值。我认为很少有人知道这个函数可以接受负值,如果你将begin设置一个负数的话,你就能从数组中获取到倒数的元素:
var array = [1, 2, 3, 4, 5, 6];
console.log(array.slice(-1)); // [6]
console.log(array.slice(-2)); // [5,6]
console.log(array.slice(-3)); // [4,5,6]
25. 全部替换
//String.replace()函数允许使用String和Regex来替换字符串,这个函数本身只能替换第一个匹配的串。但是你可以在正则表达式末尾添加/g来模拟replaceAll()函数:
var string = "john john";
console.log(string.replace(/hn/, "ana")); // "joana john"
console.log(string.replace(/hn/g, "ana")); // "joana joana"
26. 把NodeList转换成数组
//如果运行document.querySelectorAll("p")函数,它会返回一个DOM元素数组,即NodeList对象。但是这个对象并没有一些属于数组的函数,例如:sort(),reduce(),map(),filter()。为了启用这些函数,以及数组的其他的原生函数,你需要将NodeList转换为数组。要进行转换,只需使用这个函数:[] .slice.call(elements):
var elements = document.querySelectorAll("p"); // NodeList
var arrayElements = [].slice.call(elements); // 现在已经转换成数组了
var arrayElements = Array.from(elements); // 把NodeList转换成数组的另外一个方法
27. 对数组元素进行洗牌
//如果要像外部库Lodash那样对数据元素重新洗牌,只需使用这个技巧:
var list = [1, 2, 3];
console.log(list.sort(function () {
return Math.random() - 0.5
})); // [2,1,3]
28. 如果 ajax 返回单一的 json 格式,接收方需要这样再格式化一下赋值:
var str = eval("(" + msg + ")");
29. 删除前后空格 String.prototype.trim = function () { return this.replace(/(^[ | ] )|([ | ] $)/g,""); }
30. document.getElementsByTagName('*').length //查看页面有多少个 Dom 元素;
31. 按照 json 的属性值排序
var cc = [
{name: "a", age: 30},
{name: "c", age: 24},
{name: "b", age: 28},
{name: "e", age: 18},
{name: "d", age: 38}
].sort(function (obj1, obj2) {
return obj1.age - obj2.age;
});
for (var i = 0; i < cc.length; i++) {
alert(cc[i]['age']); //依次显示 18,24,28,30,38
}
32. 多点击事件获取点击的是哪个
$('#IndexLink,#IndexLink1').on('click', function (e) {
var id = e.target.id;
//id 取到的就是被点击的ID值
}
33. 锚点定位方法
window.location.hash = 'm001';
< / a >
34. 如何优雅的实现金钱格式化:1234567890 --> 1,234,567,890
//用正则魔法实现:
var test1 = '1234567890'
var format = test1.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
console.log(format) // 1,234,567,890
//非正则的优雅实现:
function formatCash(str) {
return str.split('').reverse().reduce((prev, next, index) => {
return ((index % 3) ? next : (next + ',')) + prev
})
}
console.log(formatCash('1234567890')) // 1,234,567,890
35. 实现标准JSON的深拷贝
var a = {
a: 1,
b: { c: 1, d: 2 }
}
var b=JSON.parse(JSON.stringify(a))
36. 取出一个数组中的最大值和最小值
var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
var maxInNumbers = Math.max.apply(Math, numbers);
var minInNumbers = Math.min.apply(Math, numbers);
37. javascript高逼格之Function构造函数
//很多JavaScript教程都告诉我们,不要直接用内置对象的构造函数来创建基本变量,例如var arr = new Array(2); 的写法就应该用var arr = [1, 2];的写法来取代
//但是,Function构造函数(注意是大写的Function)有点特别。Function构造函数接受的参数中,第一个是要传入的参数名,第二个是函数内的代码(用字符串来表示)。
var f = new Function('a', 'alert(a)');
f('jawil'); // 将会弹出窗口显示jawil
38. 页面到底部自动加载内容:
var divH = document.body.scrollHeight,top = document.body.scrollTop,windowH = window.screen.availHeight;
if ((top + windowH) >divH) { console.log('该加载内容了。'); }
console.log('网页正文全文高:' + document.body.scrollHeight + ' 网页被卷去的高: ' + document.body.scrollTop + ' 屏幕可用工
39. underfined、null、0、false、NaN、空字符串的逻辑结果均为false
40. 不要直接 从数组中delete或remove元素,删除对象的属性时可以使用delete。
如果对数组元素直接使用delete,其实并没有删除,只是将元素置为了undefined。数组元素删除应使用splice。
var
items = [12, 548 ,
'a'
, 2 , 5478 ,
'foo'
, 8852, ,
'Doe'
,2154 , 119 ];
items.length;
// return 11
delete
items[3];
// return true
items.length;
// return 11