JavaScript实用代码小技巧


Posted in Javascript onAugust 23, 2018

在上次的 “Chrome DevTools 你可能不知道的小技巧” 文中,得到很多开发朋友的反馈确实不知道这些小技巧。今天,我们来聊一聊在 EcmaScript5/6+ 中的一些小技巧,欢迎评论区讨论下更多技巧。

JSON.stringify

我们平时经常会用到JSON 对象,比如当我们要实现对象的深拷贝时,我们可以用JSON 对象的JSON.stringify和JSON.parse 来拷贝一个完全一样的对象,而不会对原对象产生任何引用关系。在使用localStorage 时,也会用到它,因为localStorage 只能存储字符串格式的内容,所以,我们在存之前,将数值转换成JSON字符串,取出来用的时候,再转成对象或数组。

对于JSON.stringify 方法,它可以帮我们把一个对象或数组转换成一个JSON字符串。我们通常只会用到它的第一个参数,其实它还有另外两个参数,可以让它实现一些非常好用的功能。

首先来看语法:

JSON.stringify(value[, replacer [, space]])

参数:

  • value:将要被序列化的变量的值
  • replacer:替代器。可以是函数或者是数组,如果是一个函数,则value 每个属性都要经过这个函数的处理,该函数的返回值就是最后被序列化后的值。如果是一个数组,则要求该数组的元素是字符串,且这些元素会被当做value 的键(key)进行匹配,最后序列化的结果,是只包含该数组每个元素为key 的值。
  • space:指定输出数值的代码缩进,美化格式之用,可以是数字或者字符串。如果是数字(最大为10)的话,代表每行代码的缩进是多少个空格。如果是字符串的话,该字符串(最多前十个字符)将作显示在每行代码之前。

这时候,你应该知道了。我们可以用JSON.stringify 来做序列化时的过滤,相当于我们可以自定义JSON.stringify 的解析逻辑。

使用函数过滤并序列化对象:

// 使用“函数”当替代器
function replacer(key, value) {
 if (typeof value === "string") {
 return undefined;
 }
 return value;
}
var foo = {
 foundation: "Mozilla", 
 model: "box", 
 week: 45, 
 transport: "car", 
 month: 7
};
var jsonString = JSON.stringify(foo, replacer);
// {"week":45,"month":7}

使用数组过滤并序列化对象:

// 使用“数组”当替代器
const user = {
 name: 'zollero',
 nick: 'z',
 skills: ['JavaScript', 'CSS', 'HTML5']
};
JSON.stringify(user, ['name', 'skills'], 2);
// "{
// "name": "zollero",
// "skills": [
//  "JavaScript",
//  "CSS",
//  "HTML5"
// ]
// }"

还有一个有意思的东西,是对象的toJSON 属性。

如果一个对象有toJSON 属性,当它被序列化的时候,不会对该对象进行序列化,而是将它的toJSON 方法的返回值进行序列化。

见下面的例子:

var obj = {
 foo: 'foo',
 toJSON: function () {
 return 'bar';
 }
};
JSON.stringify(obj);  // '"bar"'
JSON.stringify({x: obj}); // '{"x":"bar"}'

用 Set 来实现数组去重

在ES6 中,引入了一个新的数据结构类型:Set。而Set 与Array 的结构是很类似的,且Set 和Array 可以相互进行转换。

数组去重,也算是一个比较常见的前端面试题了,方法有很多种,这里不多赘述。下面我们看看用Set 和...(拓展运算符)可以很简单的进行数组去重。

const removeDuplicateItems = arr => [...new Set(arr)];
removeDuplicateItems([42, 'foo', 42, 'foo', true, true]);
//=> [42, "foo", true]

用块级作用域避免命名冲突

在开发的过程中,通常会遇到命名冲突的问题,就是需要根据场景不同来定义不同的值来赋值给同一个变量。下面介绍一个使用ES6 中的块级作用域 来解决这个问题的方法。

比如,在使用switchcase 时,我们可以这样做:

switch (record.type) {
 case 'added': {
 const li = document.createElement('li');
 li.textContent = record.name;
 li.id = record.id;
 fragment.appendChild(li);
 break;
 }
 case 'modified': {
 const li = document.getElementById(record.id);
 li.textContent = record.name;
 break;
 }
}

函数参数值校验

我们知道,在ES6 中,为函数增加了参数默认值的特性,可以为参数设定一些默认值,可以让代码更简洁,可维护。

其实,我们可以通过这个特性来做函数参数值的校验。

首先,函数的参数可以是任意类型的值,也可以是函数,比如下面这个:

function fix(a = getA()) {
 console.log('a', a)
}
function getA() {
 console.log('get a')
 return 2
}
fix(1);
// a 1
fix();
// get a
// a 2

可以看出,如果在调用fix 时传了参数a ,则不会执行函数getA,只有当不传递参数a 时,才会执行函数getA。

这时候,我们可以利用这一特性,为参数a 添加一个必传的校验,代码如下:

function fix(a = require()) {
 console.log('a', a)
}
function require() {
 throw new Error('缺少了参数 a')
}
fix(1);
// a 1
fix();
// Uncaught Error: 缺少了参数 a

用解构赋值过滤对象属性

在前面我们介绍了使用JSON.stringify 来过滤对象的属性的方法。这里,我们介绍另外一种使用ES6 中的解构赋值 和拓展运算符 的特性来过滤属性的方法。

比如,下面这段示例:

// 我们想过滤掉对象 types 中的 inner 和 outer 属性
const { inner, outer, ...restProps } = {
 inner: 'This is inner',
 outer: 'This is outer',
 v1: '1',
 v2: '2',
 v4: '3'
};
console.log(restProps);
// {v1: "1", v2: "2", v4: "3"}

用解构赋值获取嵌套对象的属性

解构赋值 的特性很强大,它可以帮我们从一堆嵌套很深的对象属性中,很方便地拿到我们想要的那一个。比如下面这段代码:

// 通过解构赋值获取嵌套对象的值
const car = {
 model: 'bmw 2018',
 engine: {
  v6: true,
  turbo: true,
  vin: 12345
 }
};
// 这里使用 ES6 中的简单写法,使用 { vin } 替代 { vin: vin }
const modalAndVIN = ({ model, engine: { vin }}) => {
 console.log(`model: ${model}, vin: ${vin}`);
}
modalAndVIN(car);
// "model: bmw 2018, vin: 12345"

合并对象

ES6 中新增的拓展运算符,可以用来解构数组,也可以用来解构对象,它可以将对象中的所有属性展开。

通过这个特性,我们可以做一些对象合并的操作,如下:

// 使用拓展运算符合并对象,在后面的属性会重写前面相同属性的值
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { c: 5, d: 9 };
const merged = { ...obj1, ...obj2 };
console.log(merged);
// {a: 1, b: 2, c: 5, d: 9}
const obj3 = { a: 1, b: 2 };
const obj4 = { c: 3, d: { e: 4, ...obj3 } };
console.log(obj4);
// {c: 3, d: {a: 1, b: 2, e: 4} }

使用 === 代替 ==

在JavaScript 中,=== 和== 是有很大的不同的,== 会将两边的变量进行转义,然后将转义后的值进行比较,而=== 是严格比较,要求两边的变量不仅值要相同,它们自身的类型也要相同。

JavaScript 经常被调侃成一个神奇的语言,就是因为它的转义的特性,而用== 可能会引入一些深埋的bug。远离 bug,还是要用===:

[10] == 10  // true
[10] === 10  // false
'10' == 10  // true
'10' === 10  // false
 [] == 0  // true
 [] === 0  // false
 '' == false // true
 '' === false // false

当然,在用=== 时,也会出问题,比如:

NaN === NaN // false

ES6 中提供了一个新的方法:Object.is(),它具有=== 的一些特点,而且更好、更准确,在一些特殊场景下变现的更好:

Object.is(0 , ' ');   //false
Object.is(null, undefined); //false
Object.is([1], true);  //false
Object.is(NaN, NaN);  //true

下图,是关于==、=== 和Object.is 的对比:

JavaScript实用代码小技巧

Javascript 相关文章推荐
jQuery ready函数滥用分析
Feb 16 Javascript
css值转换成数值请抛弃parseInt
Oct 24 Javascript
原生js事件的添加和删除的封装
Jul 01 Javascript
jQuery实现鼠标滑过Div层背景变颜色的方法
Feb 17 Javascript
js实现密码强度检测【附示例】
Mar 30 Javascript
浅析jquery数组删除指定元素的方法:grep()
May 19 Javascript
jquery.serialize() 函数语法及简单实例
Jul 08 Javascript
loading动画特效小结
Jan 22 Javascript
Vue.js基础学习之class与样式绑定
Mar 20 Javascript
jQuery实现的滑块滑动导航效果示例
Jun 04 jQuery
微信小程序bindinput与bindsubmit的区别实例分析
Apr 17 Javascript
原生js拖拽实现图形伸缩效果
Feb 10 Javascript
jQuery实现鼠标移到某个对象时弹出显示层功能
Aug 23 #jQuery
使用JS实现导航切换时高亮显示的示例讲解
Aug 22 #Javascript
Vue 菜单栏点击切换单个class(高亮)的方法
Aug 22 #Javascript
Vue.js点击切换按钮改变内容的实例讲解
Aug 22 #Javascript
Vue2.0点击切换类名改变样式的方法
Aug 22 #Javascript
vuejs选中当前样式active的实例
Aug 22 #Javascript
详解如何在webpack中做预渲染降低首屏空白时间
Aug 22 #Javascript
You might like
关于Sphinx创建全文检索的索引介绍
2013/06/25 PHP
PHP实现的服务器一致性hash分布算法示例
2018/08/09 PHP
ThinkPHP3.2.3框架实现执行原生SQL语句的方法示例
2019/04/03 PHP
Javascript 个人笔记(没有整理,很乱)
2007/07/07 Javascript
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
学习ExtJS form布局
2009/10/08 Javascript
Extjs中DisplayField的日期或者数字格式化扩展
2010/09/03 Javascript
js 实现日期灵活格式化的小例子
2013/07/14 Javascript
JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)
2013/12/17 Javascript
js动态修改整个页面样式达到换肤效果
2014/05/23 Javascript
jQuery中wrapAll()方法用法实例
2015/01/16 Javascript
jquery获取及设置outerhtml的方法
2015/03/09 Javascript
AngularJS基础 ng-options 指令详解
2016/08/02 Javascript
jQuery插件FusionCharts绘制2D环饼图效果示例【附demo源码】
2017/04/10 jQuery
vue.js源代码core scedule.js学习笔记
2017/07/03 Javascript
基于JavaScript实现数码时钟效果
2020/03/30 Javascript
浅谈webpack编译vue项目生成的代码探索
2017/12/11 Javascript
JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析
2019/05/22 Javascript
搭建Vue从Vue-cli到router路由护卫的实现
2019/11/14 Javascript
vue实现图片懒加载的方法分析
2020/02/05 Javascript
微信小程序实现树莓派(raspberry pi)小车控制
2020/02/12 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
[04:27]DOTA2官方论坛水友赛集锦
2013/09/16 DOTA
[51:06]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第二场 1月26日
2021/03/11 DOTA
python检测lvs real server状态
2014/01/22 Python
Python之py2exe打包工具详解
2017/06/14 Python
pytorch 实现查看网络中的参数
2020/01/06 Python
为什么称python为胶水语言
2020/06/16 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
python 获取谷歌浏览器保存的密码
2021/01/06 Python
EVE LOM英国官网:全世界最好的洁面膏
2017/10/30 全球购物
庆元旦广播稿
2014/02/10 职场文书
消防安全宣传标语
2014/06/07 职场文书
2014向国旗敬礼网上签名活动总结
2014/09/27 职场文书
2019新员工试用期转正工作总结范文
2019/08/21 职场文书
2022年显卡天梯图(6月更新)
2022/06/17 数码科技