JavaScript中的一些实用小技巧总结

前言

这篇文章主要记录一下平时自己实践得到的, 博客中学习的以及在一些项目源码中看到的 javascript 技巧。有些东西可以说是奇淫技巧,有些可能是 ES6+ 中一些比较具有实用性的新语法。

&& 和 || 的妙用

有时候我们需要在某个函数或变量为 true 时执行另外一个函数。例如:

const task1 = () => {
 console.log('执行 task1');
 return Math.random() >= 0.5;
}

const task2 = () => console.log('task1 执行成功后执行 task2');
if (task1()) task2();

上面的 if 语句可以使用 && 直接简写为:

task1() && task2();

如果还要在 task1 失败(也就是task1返回false)后执行 task3, 可以使用:

const task3 = () => console.log('task1 执行失败后执行 task3');
task1() && task2() || task3();

本质上还是利用了 && 和 || 的短路特性。

其实这里使用条件运算符也是可以的:

task1() ? task2() : task3();

下面展示一个我最近使用 react hooks 开发的项目的的一个代码片段:

const ProfileItem = (props) => {
 const { name, value, render } = props;

 return (
  <div className="profile-item">
   <span className="item-name">{name}</span>
   <form action="">
    {/* 根据是否有 render 这个 props 来返回不同的内容 */}
    {render && render(props) || <SimpleProfileItemContent value={value}/>}
   </form>
  </div>
 )
}

函数默认值

ES5 版本

使用短路或操作符来设置函数默认值的方式其实很常见。但是有一些坑,下面展示的代码中当默认值参数为一个数字时,传参为 0 还是会使用默认值,必须对 y 为 0 的时候单独进行判断。

const pow = (x, y) => {
 y = y || 2;

 let result = 1;
 for (let i = 0, max = y; i < max; i++) {
  result *= x;
 }

 return result;
}

console.log(pow(2)); // => 4
console.log(pow(2, 3)); // => 8

// 当 y 传值为 0 时, y 取值 2
console.log(pow(2, 0)); // => 4

ES6 版本

ES6 在语法层面提供的默认值语法就靠谱的多了

const pow = (x, y=2) => {
 let result = 1;
 for (let i = 0, max = y; i < max; i++) {
  result *= x;
 }

 return result;
}

console.log(pow(2)); // => 4
console.log(pow(2, 3)) // => 8
console.log(pow(2, 0)); // => 1

类数组转数组

类数组指的是像 arguments ,jquery 对象一样可以使用下标访问还有 length 属性的和数组很像但并不是数组的一类对象。

类数组没有 slice, map 等集合函数,这也是为什么我们有时候需要将类数组转换成数组的原因。

function func() {
 for (let i = 0, max = arguments.length; i < max; i++) {
  console.log(arguments[i]);
 }

 console.log(Array.isArray(arguments)); // => false
 // 类数组没有 slice, forEach, map 等集合函数
 console.log(arguments.slice === undefined); // => true
}

func('Google', 'facebook', 'Microsoft');
// =>
// Google
// facebook
// Microsoft

ES5 中的转换方法

将 Array 原型中的 slice 方法绑定到 arguments 对象上调用,并且不传参数目的为了让其返回所有的元素。

function func() {
 const array = Array.prototype.slice.call(arguments);
 console.log(array.slice(0, 1));
}

func('Google', 'facebook', 'Microsoft'); // => [ 'Google' ]

ES6 中的转换方法

ES6 将类数组转换成数组的方法多一些。

使用扩展运算符

function func() {
 console.log([...arguments])
}

func('Google', 'facebook', 'Microsoft'); // [ 'Google', 'facebook', 'Microsoft' ]

使用 Array.from

function func() {
 console.log(Array.from(arguments))
}

func('Google', 'facebook', 'Microsoft'); // [ 'Google', 'facebook', 'Microsoft' ]

构造一个连续整数的数组

这里就直接给出我觉得最好的方法了

// 输出 2 开始连续的8个整数
const array = Array.from({ length: 8}).map((ele, index) => index + 2);
console.log(array); // => [ 2, 3, 4, 5, 6, 7, 8, 9 ] 
// 评论区指出有更简洁的版本, Array.from 自带的映射函数
const array = Array.from({ length: 8}, (ele, index) => index + 2);
console.log(array); // => [ 2, 3, 4, 5, 6, 7, 8, 9 ] 

函数参数使用解构赋值

函数参数比较多的时候我们往往会让参数直接接受一个配置对象。但是使用对象参数我们无法设置默认值,在函数体中使用对象参数时还需要使用通过对象参数来访问,当访问次数比较多或者嵌套比较深就会觉得不方便。在函数参数中使用解构赋值就解决了上面的问题。

// 必须给对象参数设置默认值, 不然传参数时因为没有解构对象会报错
const getUsers = ({
 offset=0,
 limit=1,
 orderBy="salary"
}={}) => {
 // 根据条件查询数据库返回用户数据
 console.log({ offset, limit, orderBy });
}

getUsers({ offset: 10, limit: 20,orderBy: 'age' }); // => { offset: 10, limit: 20, orderBy: 'age' }
getUsers();// => { offset: 0, limit: 1, orderBy: 'salary' }

使用 !! 将其它类型转换成 bool 型

console.log(!!{}); // true
console.log(!!0); // false
console.log(!![]); // true
console.log(!!undefined); // false

const httpGet = (url, retry) => {
 if (!!retry) {
  // 超时重发
 }
}

JSON.stringify

深度克隆

使用先序列化再反序列化这种方式来深度克隆对象在一般情况下很方便,缺点就是无法克隆函数以及继承的属性。
如果还要克隆函数属性,推荐使用 lodash 的 cloneDeep。

const me = {
  name: 'lyreal666',
  age: 23,
  speak() {
    console.log(`Hello, I'm ly!`);
  }
}

const clonedMe = JSON.parse(JSON.stringify(me));
console.log(clonedMe); // => { name: 'lyreal666', age: 23 }
console.log(clonedMe.speak === undefined); // => true

使用第二个和第三参数

JSON.stringify 的第二个参数是用来对属性值进行处理的,第三个参数则是用来指定输出的 json 字符串的缩进长度,可以传数字也可以传字符串。

const me = {
  name: 'lyreal666',
  age: 23,
  speak() {
    console.log(`Hello, I'm ly!`);
  }
}

const jsonStr = JSON.stringify(me, (key, value) => key === 'name' ? '老余' : value, 2);

console.log(jsonStr);
/* =>
{
 "name": "老余",
 "age": 23
}
*/

优雅的遍历对像

使用解构赋值和 Object.entries。

const me = {
  name: 'lyreal666',
  age: 23,
  speak() {
    console.log(`Hello, I'm ly!`);
  }
}

for (const [key, value] of Object.entries(me)) {
  console.log(`${key}: ${value}`);
}

/* =>
name: lyreal666
age: 23
speak: speak() {
    console.log(`Hello, I'm ly!`);
  }
*/

清空数组的最快方法

评论区有人说这种直接修改 length 的做法是有问题的, 我之前也看过关于清空数组的方法的讨论, 但是我觉得一般情况下这样用是没什么问题的, 既简单, 又不用重新分配内存给新数组。

const array = [1, 2, 3, 4];
array.length = 0;
console.log(array); // => []

// 网友指出可以更好的方式是直接赋值空数组
let array = [1, 2, 3, 4];
array = [];

判断一个整数是否是 -1

// ~ 操作符的运算规律可以简单记作将加一的结果取反
console.log(~1); // => -2
console.log(~0); // => -1
console.log(~(-3)); // => 2
console.log(~(-1)); // => 0

const number = -2;

// 判断一个数是否为 -1
if (!~number) {
  // 当 number 是 -1 的操作...
}

立即执行函数

立即执行函数可以让我们的代码中的变量不污染外部变量,常见的使用方式是像下面这样的。

// 使用括号将函数括起来调用
(function(window, $) {
  // 内部代码
}) (window, jQuery)

更优雅的方式是下面这种,事实上很多其它的算术运算符比如 +, -, *, ~ 等也是可以的。

! function(window, $) {
  // 内部代码
} (window, jQuery)

// 还可以使用 +, -, * 等
+ function(window, $) {
  // 内部代码
} (window, jQuery)

// 更神奇的是还可以用 new, typeof 等操作符
new function(window, $) {
  // 内部代码
} (window, jQuery);

使用 set 来对数组去重复

console.log([...new Set([1, 3, 1, 2, 2, 1])]); // => [ 1, 3, 2 ]

使用 reduce 连乘或连加

const array = [ 1, 2, 3, 4];
// 连加
console.log(array.reduce((p, c) => p + c)); // => 10
// 连乘
console.log(array.reduce((p, c) => p * c)); // => 24

取整

Math 中的一堆取整函数这里就不说了,主要是提一些比较巧妙地取整方式。

console.log(~~3.14); // => 3
console.log(~~(-2.5)); // => -2

console.log(6.18 | 0); // => 6
console.log(-3.6 | 0); // => -3

console.log(9.9 >> 0); // => 9
console.log(-2.1 >> 0); // => -2

// superagent 是一个很实用的发送 http 请求的 node 模块,它对返回码的处理就用到了 |
var type = status / 100 | 0;

// status / class
res.status = status;
res.statusType = type;

// basics
res.info = 1 == type;
res.ok = 2 == type;
res.clientError = 4 == type;
res.serverError = 5 == type;
res.error = 4 == type || 5 == type;

使用 + 将其它类型转换成 number 类型

console.log(+'3.14'); // => 3.14
console.log(typeof +'3.14') // => number

const sleep = (milliseconds) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(), milliseconds);
    });
}

// 当然这里可以考虑使用 console.time 来测试
! async function main() {
  const start = +new Date();
  await sleep(3000);
  const end = +new Date();
  console.log(`执行了${end - start}`); // 执行了 3002
}();

使用科学计数法表示大数字

const str1 = 'hello';
const str2 = ' world'

console.time('测试 + 拼接字符串');
for (let i = 0; i < 200000000; i++) {
  const joinedStr = str1 + str2;
}
console.timeEnd('测试 + 拼接字符串');

console.time('测试模板字符串拼接字符串');
// 使用科学计数法比打 8 个 0 方便不少
for (let i = 0; i < 2E8; i++) {
  const joinedStr =`${str1}${str2}`;
}
console.timeEnd('测试模板字符串拼接字符串')

/* =>
测试 + 拼接字符串: 3238.037ms
测试模板字符串拼接字符串: 3680.225ms
*/

交换变量值

直接利用解构赋值

let a = 666;
let b = 999;
[a, b] = [b, a];
console.log({ a, b }); // => { a: 999, b: 666 }

获取随机字符串

截取下标 2 开始后的字符串是因为不需要 Math.random() 返回的小数构成的字符串的 0. 这两个字符。使用 36 进制可以制造字符种类更多些的随机字符串

console.log(Math.random().toString(16).substring(2)); // 13位 => 45d9d0bb10b31
console.log(Math.random().toString(36).substring(2)); // 11位 => zwcx1yewjvj

扁平化数组

ES 2019 新增了 Array.prototype.flat,目前 chrome 最新正式版 73.0.3683.103 已经支持了, node 最新的 LTS 10.15.3 还不支持, node 最新开发版 11.13.0 是支持的。这里贴一个在掘金一个兄弟面经里面看到的比较 hack 的方法,这里要注意根据情况做类型转换。

const array = [1, [2, [3, 4], 5], 6, 7];
console.log(array.toString().split(',').map(ele => Number.parseInt(ele))); // => [ 1, 2, 3, 4, 5, 6, 7 ]

最近面试腾讯,阿里前端实习岗真的是一言难尽,后面打算整篇文章聊聊我最近的面试经历。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • 12个非常实用的JavaScript小技巧【推荐】

    这篇文章中将给大家分享12个有关于JavaScript的小技巧.这些小技巧可能在你的实际工作中或许能帮助你解决一些问题. 使用!!操作符转换布尔值 有时候我们需要对一个变量查检其是否存在或者检查值是否有一个有效值,如果存在就返回true值.为了做这样的验证,我们可以使用!!操作符来实现是非常的方便与简单.对于变量可以使用!!variable做检测,只要变量的值为:0.null." ".undefined或者NaN都将返回的是false,反之返回的是true.比如下面的示例: funct

  • Javascript 实用小技巧

    //自定义的apply,call Function.prototype.apply = function (obj, argu) {  if (obj) obj.constructor.prototype._caller = this;   var argus = new Array();  for (var i=0;i<argu.length;i++)   argus[i] = "argu[" + i + "]";  var r;  eval("r

  • JavaScript编程的10个实用小技巧

    在这篇文章中,我将列出10个Javascript实用小技巧,主要面向Javascript新手和中级开发者.希望每个读者都能至少从中学到一个有用的技巧. 1.变量转换 看起来很简单,但据我所看到的,使用构造函数,像Array()或者Number()来进行变量转换是常用的做法.始终使用原始数据类型(有时也称为字面量)来转换变量,这种没有任何额外的影响的做法反而效率更高. 复制代码 代码如下: var myVar   = "3.14159",str     = ""+ m

  • 分享12个非常实用的JavaScript小技巧

    在这篇文章中将给大家分享12个有关于JavaScript的小技巧.这些小技巧可能在你的实际工作中或许能帮助你解决一些问题. 使用!!操作符转换布尔值 有时候我们需要对一个变量查检其是否存在或者检查值是否有一个有效值,如果存在就返回true值.为了做这样的验证,我们可以使用!!操作符来实现是非常的方便与简单.对于变量可以使用!!variable做检测,只要变量的值为:0.null." ".undefined或者NaN都将返回的是false,反之返回的是true.比如下面的示例: func

  • vue.js项目中实用的小技巧汇总

    前言 Vue.js 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用. # 在Vue 项目中引入Bootstrap 有时在vue项目中会根据需求引入Bootstrap,而Bootstrap又是依赖于jQuery的,在使用npm安装时,可能会出现一系列的错误 1.安装jQuery

  • JavaScript实用代码小技巧

    在上次的 "Chrome DevTools 你可能不知道的小技巧" 文中,得到很多开发朋友的反馈确实不知道这些小技巧.今天,我们来聊一聊在 EcmaScript5/6+ 中的一些小技巧,欢迎评论区讨论下更多技巧. JSON.stringify 我们平时经常会用到JSON 对象,比如当我们要实现对象的深拷贝时,我们可以用JSON 对象的JSON.stringify和JSON.parse 来拷贝一个完全一样的对象,而不会对原对象产生任何引用关系.在使用localStorage 时,也会用到

  • JavaScript编程开发中的五个实用小技巧

    真是五个很quick的小提示: 只在<form>元素上使用submit事件 如果要在form中绑定事件处理程序时,应该只在<form>元素上绑定submit事件,而不是给提交按钮绑定click事件. March:这个方式固然很好,但是,公司开发时使用了Web Flow,一个页面就一个大form,而里面可能有若干个提交按钮,所以不得不把部分事件处理程序绑定在了提交按钮的click事件上. 可点击的都应该是链接 不要给除锚元素(<a>)以外的元素绑定click事件.这一点对

  • JavaScript中的一些实用小技巧总结

    前言 这篇文章主要记录一下平时自己实践得到的, 博客中学习的以及在一些项目源码中看到的 javascript 技巧.有些东西可以说是奇淫技巧,有些可能是 ES6+ 中一些比较具有实用性的新语法. && 和 || 的妙用 有时候我们需要在某个函数或变量为 true 时执行另外一个函数.例如: const task1 = () => { console.log('执行 task1'); return Math.random() >= 0.5; } const task2 = ()

  • JavaScript中Array的实用操作技巧分享

    一.关于Array Array的创建很灵活,可以使用Array构造函数,也可以直接创建数组"字面量". var arr = new Array(); //[] var brr = Array(); //[] 两者等效 var arr = Array(3); //[] arr.length; //3 长度为3的空数组 var arr = Array(22,33,'qq',{}); //[22, 33, "qq", Object] var brr = [22,33,'q

  • JavaScript开发的七个实用小技巧(很有用)

    目录 1. 数组求和 2. 使用 length 属性更改数组 3. 数组元素随机打乱 4. 过滤唯一值 5. 逗号运算符 6. 使用数组解构交换数据元素 7. 使用 && 代替 If 条件判断为真的条件 总结 本文译文,采用意译. 下面这些方法对于我来说很有作用,自从我发现了这些操作. 1. 数组求和 假设你有下面的数字数组:let numbers = [2,52,55,5]. 计算求和,我们会想到使用 for,是吧. 但是我们可以使用这行代码完成let sum = numbers.red

  • Vue中$once的两个实用小技巧分享

    目录 前言 清除定时器 $once/$emit + async/await 实现 Dialog 同步执行 总结 前言 在 Vue 中有很多 API 都有很实用的地方,只是需要挖掘适用的场景,这里整理出了 $once 的两个小技巧,也是在平常工作中用的比较多的,分享给大家,希望对大家能有帮助. 清除定时器 定时器大家用的应该也不少,像我一开始一般都是这样写的,在 created 中创建定时器,在 beforeDestroy 中销毁定时器. <script> export default { na

  • 关于Go你不得不知道的一些实用小技巧

    目录 Go 箴言 Go 之禅 代码 使用 go fmt 格式化 多个 if 语句可以折叠成 switch 用 chan struct{} 来传递信号, chan bool 表达的不够清楚 30 * time.Second 比 time.Duration(30) * time.Second 更好 用 time.Duration 代替 int64 + 变量名 按类型分组 const 声明,按逻辑和/或类型分组 var 不要在你不拥有的结构上使用 encoding/gob 不要依赖于计算顺序,特别是在

  • Kotlin开发的一些实用小技巧总结

    前言 随着Google I/O大会的召开,Google宣布将支持Kotlin作为Android的开发语言,最近关于Kotlin的文章.介绍就异常的活跃. 本文主要给大家介绍了关于Kotlin开发的一些实用小技巧,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 1.Lazy Loading(懒加载) 延迟加载有几个好处.延迟加载能让程序启动时间更快,因为加载被推迟到访问变量时. 这在使用 Kotlin 的 Android 应用程序而不是服务器应用程序中特别有用.对于 Androi

  • Python中Collection的使用小技巧

    本文所述实例来自独立软件开发者 Alex Marandon,在他的博客中曾介绍了数个关于 Python Collection 的实用小技巧,在此与大家分享.供大家学习借鉴之用.具体如下: 1.判断一个 list 是否为空 传统的方式: if len(mylist): # Do something with my list else: # The list is empty 由于一个空 list 本身等同于 False,所以可以直接: if mylist: # Do something with

  • jQuery实用小技巧_输入框文字获取和失去焦点的简单实例

    jQuery实用小技巧_输入框文字获取和失去焦点的简单实例 <input id="txt" class="text1" type="text" /> <script src="js/jquery-1.7.1.min.js"></script> <script type="text/javascript"> $(function () { $("inp

  • 常用的10个Python实用小技巧

    大家好,都说追女孩方法大于态度,学Python也是,今天就给大家分享的是我在用Python编写程序时常用的一些小技巧. 1.多次打印同一个字符 在Python中,不用特地写一个函数来重复打印同一个字符,直接使用Print就可以 tem = 'I Love Python ' print(tem * 3) I Love Python I Love Python I Love Python 2.在函数内部使用生成器 在写Python程序时,我们可以在函数内部直接使用生成器,这样可以使代码更简洁. su

随机推荐