书接上文:细数 JavaScript 实用黑科技(一)javascript
本文介绍 独孤九剑和两篇最高内功心法。vue
!! 操做符:!!variable 。
!! 能够将变量转换为布尔值。
!! 能够把任何类型的值转换为布尔值,而且只有当这个变量的值为 0 / null / "" / NaN / undefined 的时候才会返回 false,其余状况都返回 true。java
!!'' // false !!' ' // true !!0 // false !!null // false !!undefined // false !!NaN // false !!123 // true !![] // true
它只能做用于字符串数值,不然就会返回 NaN(不是数字)。
例子:node
function toNumber(strNumber) { return +strNumber; } console.log(toNumber("1234")); // 1234 console.log(toNumber("abc")); // NaN
而且此方法也可做用于 Date 函数,这是它将返回时间戳:react
console.log(+new Date()) // 1461288164385
if (token) { getUser(); }
能够经过使用 && 操做符组合两个变量来缩短它。git
好比前面这段代码能够缩短为:github
token && getUser();
若是第一个参数返回 false,第二个值将被做为默认值。用来设置默认参数。web
function getUser(token) { var token = token || "XXXXXXXXXX"; console.log('token',token) // 用 token 来异步请求数据 // ....... } getUser(666666); // 666666 getUser(); // XXXXXXXXXX
固然,ES6 已经支持默认值参数设置了。
若是你想学到更多工做中会用到的 ES6 的新特性,请看小汪写过的:那些必会用到的 ES6 精粹segmentfault
大多数人的作法:数组
var arr = [123, 456, 789]; var len = arr.length; var end = arr[len-1] console.log('end:', end) // 'end:' 789
优化方法:
var array = [1, 2, 3, 4, 5, 6]; console.log( array.slice(-1) ); // [6] console.log( array.slice(-1)[0] ); // 6 console.log( array.slice(-2) ); // [5,6] console.log( array.slice(-3) ); // [4,5,6]
不适用 Lodash 等这些库打乱数组元素顺序,你可使用这个技巧:
var list = [1,2,3]; console.log( list.sort(function() { Math.random() - 0.5 }) ); // [2,1,3]
数组的 slice方法能够将“相似数组的对象”变成真正的数组。
var arr = Array.prototype.slice.call(arrayLike);
var elements = document.querySelectorAll("p"); // NodeList 节点列表对象。但这个对象并不具备数组的所有方法,如 sort(), reduce(), map(), filter() var arrayElements = [].slice.call( elements ); // 如今 NodeList 是一个数组 var arrayElements = Array.from( elements ); // 这是另外一种转换 NodeList 到 Array 的方法
好比,当数组中有 10 个元素,而你只想获取其中前 5 个的话,你能够截断数组,经过设置 array.length = 5 使其更小。
var array = [1,2,3,4,5,6]; console.log( array.length ); // 6 array.length = 3; console.log( array.length ); // 3 console.log( array ); // [1,2,3]
通常人合并两个数组的话,一般会使用 Array.concat()。
var array1 = [1,2,3]; var array2 = [4,5,6]; console.log(array1.concat(array2)); // [1,2,3,4,5,6];
然而,这个函数并不适用于合并大的数组,由于它须要建立一个新的数组,而这会消耗不少内存。
这时,你可使用 Array.push.apply( arr1, arr2 ) 来代替建立新的数组,它能够把第二个数组合并到第一个中,从而较少内存消耗:
var array1 = [1,2,3]; var array2 = [4,5,6]; console.log( array1.push.apply(array1, array2) ); // [1,2,3,4,5,6];
函数自己也是一个值,也有本身的做用域。它的做用域与变量同样,就是其声明时所在的做用域,与其运行时所在的做用域无关。
// 先来一道题,看看输出什么 var a = 1; var x = function () { console.log(a); }; function f() { var a = 2; x(); } f() // 1
上面代码中,函数 x 是在函数 f 的外部声明的,因此它的做用域绑定外层,内部变量 a 不会到函数 f 体内取值,因此输出 1,而不是 2。
总之,函数执行时所在的做用域,是定义时的做用域,而不是调用时所在的做用域。
很容易犯错的一点是,若是函数 A 调用函数 B,却没考虑到函数 B 不会引用函数 A 的内部变量。
// 再来一道题,看看输出什么 var x = function () { console.log(a); }; function y(f) { var a = 2; f(); } y(x) // ReferenceError: a is not defined
上面代码将函数 x 做为参数,传入函数 y。可是,函数 x 是在函数 y 体外声明的,做用域绑定外层,所以找不到函数 y 的内部变量 a,致使报错。
一样的,函数体内部声明的函数,做用域绑定函数体内部。
function foo() { var x = 1; function bar() { console.log(x); } return bar; } var x = 2; var f = foo(); f() // 1
上面代码中,函数 foo 内部声明了一个函数 bar,bar 的做用域绑定 foo。当咱们在 foo 外部取出 bar 执行时,变量 x 指向的是 foo 内部的 x,而不是 foo 外部的 x。正是这种机制,构成了 “闭包” 现象。
闭包简单理解,请看个人笔记: 闭包
当即调用的函数表达式”(Immediately-Invoked Function Expression),简称 IIFE。
一般写法:
(function(){ /* code */ }()); // 或者 (function(){ /* code */ })();
注意,上面两种写法最后的分号都是必须的。若是省略分号,遇到连着两个 IIFE,可能就会报错。
// 报错 (function(){ /* code */ }()) (function(){ /* code */ }())
上面代码的两行之间没有分号,JavaScript 会将它们连在一块儿解释,将第二行解释为第一行的参数。
IIFE 的目的有两个:
例子:
// 写法一 var tmp = newData; processData(tmp); storeData(tmp); // 写法二 (function () { var tmp = newData; processData(tmp); storeData(tmp); }());
上面代码中,写法二比写法一更好,由于彻底避免了污染全局变量。
独孤九剑共九式和两篇最高内功心法都在这里面了,大侠学会后,除恶惩奸,遨游江湖吧!!!
若是你以为该文章对你有帮助,欢迎到个人 github,star 一下,谢谢。
参考教程: 《JavaScript 语言入门教程》
参考文章:12 个很是有用的 JavaScript Hacks
你觉得本文就这么结束了 ? 精彩在后面 !!!
对 全栈修炼 有兴趣的朋友能够扫下方二维码关注个人公众号
我会不按期更新有价值的内容,长期运营。
关注公众号并回复 福利 可领取免费学习资料,福利详情请猛戳: Python、Java、Linux、Go、node、vue、react、javaScript