We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
书接上文:细数 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")); // 1234 console.log(toNumber("abc")); // NaN
并且此方法也可作用于 Date 函数,这是它将返回时间戳:
console.log(+new Date()) // 1461288164385
if (token) { getUser(); }
可以通过使用 && 操作符组合两个变量来缩短它。
比如前面这段代码可以缩短为:
token && getUser();
如果第一个参数返回 false,第二个值将被作为默认值。用来设置默认参数。
function getUser(token) { var token = token || "XXXXXXXXXX"; console.log('token',token) // 用 token 来异步请求数据 // ....... } getUser(666666); // 666666 getUser(); // 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] ); // 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]
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 一下,谢谢。
github 地址
参考教程: 《JavaScript 语言入门教程》 参考文章:12 个非常有用的 JavaScript Hacks
你以为本文就这么结束了 ? 精彩在后面 !!!
The text was updated successfully, but these errors were encountered:
类数组转化为数组还可以用解构
var elements = document.querySelectorAll("p"); const elementArr = [...elements];
Sorry, something went wrong.
第六式. 打乱数组元素的顺序 需要 return Math.random() -0.5
biaochenxuying
No branches or pull requests
前言
书接上文:细数 JavaScript 实用黑科技(一)
本文介绍 独孤九剑和两篇最高内功心法。
第一式. !!
!! 操作符:!!variable 。
!! 可以将变量转换为布尔值。
!! 可以把任何类型的值转换为布尔值,并且只有当这个变量的值为 0 / null / "" / NaN / undefined 的时候才会返回 false,其他情况都返回 true。
第二式. +
它只能作用于字符串数值,否则就会返回 NaN(不是数字)。
例子:
并且此方法也可作用于 Date 函数,这是它将返回时间戳:
第三式. if (条件)
可以通过使用 && 操作符组合两个变量来缩短它。
比如前面这段代码可以缩短为:
第四式. 短路表达式 ||
如果第一个参数返回 false,第二个值将被作为默认值。用来设置默认参数。
当然,ES6 已经支持默认值参数设置了。
如果你想学到更多工作中会用到的 ES6 的新特性,请看小汪写过的:那些必会用到的 ES6 精粹
第五式. 获取数组中最后的元素
大多数人的做法:
优化方法:
第六式. 打乱数组元素的顺序
不适用 Lodash 等这些库打乱数组元素顺序,你可以使用这个技巧:
第七式. 伪数组转换为真数组
第八式. 截断数组
比如,当数组中有 10 个元素,而你只想获取其中前 5 个的话,你可以截断数组,通过设置 array.length = 5 使其更小。
第九式. 合并数组
一般人合并两个数组的话,通常会使用 Array.concat()。
然而,这个函数并不适用于合并大的数组,因为它需要创建一个新的数组,而这会消耗很多内存。
这时,你可以使用 Array.push.apply( arr1, arr2 ) 来代替创建新的数组,它可以把第二个数组合并到第一个中,从而较少内存消耗:
内功心法. 易混淆点
函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
上面代码中,函数 x 是在函数 f 的外部声明的,所以它的作用域绑定外层,内部变量 a 不会到函数 f 体内取值,所以输出 1,而不是 2。
总之,函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。
很容易犯错的一点是,如果函数 A 调用函数 B,却没考虑到函数 B 不会引用函数 A 的内部变量。
上面代码将函数 x 作为参数,传入函数 y。但是,函数 x 是在函数 y 体外声明的,作用域绑定外层,因此找不到函数 y 的内部变量 a,导致报错。
同样的,函数体内部声明的函数,作用域绑定函数体内部。
上面代码中,函数 foo 内部声明了一个函数 bar,bar 的作用域绑定 foo。当我们在 foo 外部取出 bar 执行时,变量 x 指向的是 foo 内部的 x,而不是 foo 外部的 x。正是这种机制,构成了 “闭包” 现象。
闭包简单理解,请看我的笔记: 闭包
立即调用的函数表达式
立即调用的函数表达式”(Immediately-Invoked Function Expression),简称 IIFE。
通常写法:
注意,上面两种写法最后的分号都是必须的。如果省略分号,遇到连着两个 IIFE,可能就会报错。
上面代码的两行之间没有分号,JavaScript 会将它们连在一起解释,将第二行解释为第一行的参数。
IIFE 的目的有两个:
例子:
上面代码中,写法二比写法一更好,因为完全避免了污染全局变量。
最后
独孤九剑共九式和两篇最高内功心法都在这里面了,大侠学会后,除恶惩奸,遨游江湖吧!!!
如果你觉得该文章对你有帮助,欢迎到我的 github,star 一下,谢谢。
github 地址
参考教程: 《JavaScript 语言入门教程》
参考文章:12 个非常有用的 JavaScript Hacks
你以为本文就这么结束了 ? 精彩在后面 !!!
The text was updated successfully, but these errors were encountered: