资讯专栏INFORMATION COLUMN

细数 JavaScript 实用黑科技(二)

马忠志 / 3011人阅读

摘要:前言书接上文细数实用黑科技一本文介绍独孤九剑和两篇最高内功心法。可以将变量转换为布尔值。可以把任何类型的值转换为布尔值,并且只有当这个变量的值为的时候才会返回,其他情况都返回。同样的,函数体内部声明的函数,作用域绑定函数体内部。

前言

书接上文:细数 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 (条件)
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]
第七式. 伪数组转换为真数组

数组的 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 的目的有两个:

一是不必为函数命名,避免了污染全局变量;

二是 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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97958.html

相关文章

  • 细数 JavaScript 实用科技(一)

    摘要:小汪经过实践得出以下用途。空数组的类型也是,这表示在内部,数组本质上只是一种特殊的对象。调用函数时,某个参数未设置任何值,这时就可以传入,表示该参数为空。前端还是很有未来的下节内容细数实用黑科技二。 showImg(https://segmentfault.com/img/remote/1460000016507838); 前言 只有深入学精一门语言,学其他语言才能更好地举一反三,触类...

    ConardLi 评论0 收藏0
  • 细数你不得不知的容器安全工具

    摘要:你首先需要了解的安全工具之一就是。是另一个可为进行安全漏洞扫描的工具。和相似,是的安全审核工具。和其他容器安全工具不同,使用创建自定义配置文件非常容易。月日,北京海航万豪酒店,容器技术大会即将举行。 网络安全问题的重要性大概毋庸置疑,最近无数关于恶意软件和安全漏洞的消息已充分证明了这一点。 假如你要管理一个Docker环境,并希望帮助自己的公司或用户在下一个大漏洞来临时避免遇到麻烦,那...

    刘德刚 评论0 收藏0
  • 细数你不得不知的容器安全工具

    摘要:你首先需要了解的安全工具之一就是。是另一个可为进行安全漏洞扫描的工具。和相似,是的安全审核工具。和其他容器安全工具不同,使用创建自定义配置文件非常容易。月日,北京海航万豪酒店,容器技术大会即将举行。 网络安全问题的重要性大概毋庸置疑,最近无数关于恶意软件和安全漏洞的消息已充分证明了这一点。 假如你要管理一个Docker环境,并希望帮助自己的公司或用户在下一个大漏洞来临时避免遇到麻烦,那...

    zhoutk 评论0 收藏0
  • 这些JavaScript编程科技,装逼指南,高逼格代码,让你惊叹不已

    摘要:但是,构造函数注意是大写的有点特别。构造函数接受的参数中,第一个是要传入的参数名,第二个是函数内的代码用字符串来表示。 Javascript是一门很吊的语言,我可能学了假的JavaScript,哈哈,大家还有什么推荐的,补充送那啥邀请码。 本文秉承着:你看不懂是你SB,我写的代码就要牛逼。 1、单行写一个评级组件 ★★★★★☆☆☆☆☆.slice(5 - rate, 10 - rate...

    曹金海 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<