前言书接上文:细数 JavaScript 实用黑科技(一)本文介绍 独孤九剑和两篇最高内功心法。第一式. !!!! 操作符:!!variable 。!! 可以将变量转换为布尔值。!! 可以把任何类型的值转换为布尔值,并且只有当这个变量的值为 0 / null / "" / NaN / undefined 的时候才会返回 false,其他情况都返回 true。!!’’ // false!!’ ‘// true!!0// false!!null// false!!undefined// false!!NaN// false!!123// true!![]// true第二式. +它只能作用于字符串数值,否则就会返回 NaN(不是数字)。例子:function toNumber(strNumber) { return +strNumber;}console.log(toNumber(“1234”)); // 1234console.log(toNumber(“abc”)); // NaN并且此方法也可作用于 Date 函数,这是它将返回时间戳:console.log(+new Date()) // 1461288164385第三式. if (条件)if (token) { getUser();}可以通过使用 && 操作符组合两个变量来缩短它。比如前面这段代码可以缩短为:token && getUser();第四式. 短路表达式 ||如果第一个参数返回 false,第二个值将被作为默认值。用来设置默认参数。function getUser(token) { var token = token || “XXXXXXXXXX”; console.log(’token’,token) // 用 token 来异步请求数据 // …….}getUser(666666);// 666666getUser();// XXXXXXXXXX当然,ES6 已经支持默认值参数设置了。如果你想学到更多工作中会用到的 ES6 的新特性,请看小汪写过的:那些必会用到的 ES6 精粹第五式. 获取数组中最后的元素大多数人的做法: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] ); // 6console.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 ); // 6array.length = 3;console.log( array.length ); // 3console.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 的目的有两个:一是不必为函数命名,避免了污染全局变量;二是 IIFE 内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。例子:// 写法一var tmp = newData;processData(tmp);storeData(tmp);// 写法二(function () { var tmp = newData; processData(tmp); storeData(tmp);}());上面代码中,写法二比写法一更好,因为完全避免了污染全局变量。最后独孤九剑共九式和两篇最高内功心法都在这里面了,大侠学会后,除恶惩奸,遨游江湖吧!!!如果你觉得该文章对你有帮助,欢迎到我的 github,star 一下,谢谢。github 地址参考教程: 《JavaScript 语言入门教程》参考文章:12 个非常有用的 JavaScript Hacks你以为本文就这么结束了 ? 精彩在后面 !!!对 全栈开发 有兴趣的朋友可以扫下方二维码关注我的公众号,我会不定期更新有价值的内容。微信公众号:乐趣区分享 前端、后端开发等相关的技术文章,热点资源,全栈程序员的成长之路。关注公众号并回复 福利 便免费送你视频资源,绝对干货。福利详情请点击: 免费资源分享–Python、Java、Linux、Go、node、vue、react、javaScript
...