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对象和DOM对象相互转化
Apr 24 Javascript
javascript 通用简单的table选项卡实现
May 07 Javascript
选择复选框按钮置灰否则按钮可用
May 22 Javascript
node.js中的buffer.write方法使用说明
Dec 10 Javascript
PHP实现的各种中文编码转换类分享
Jan 23 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
Jul 14 Javascript
iview给radio按钮组件加点击事件的实例
Sep 30 Javascript
关于axios不能使用Vue.use()浅析
Jan 12 Javascript
详解vue组件开发脚手架
Jun 15 Javascript
解决layui中table异步数据请求不支持自定义返回数据格式的问题
Aug 19 Javascript
微信小程序HTTP接口请求封装代码实例
Sep 05 Javascript
解决Vue在Tomcat8下部署页面不加载的问题
Nov 12 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
php数组函数序列之sort() 对数组的元素值进行升序排序
2011/11/02 PHP
PHP中大于2038年时间戳的问题处理方案
2015/03/03 PHP
php实现汉字验证码和算式验证码的方法
2015/03/07 PHP
ThinkPHP5.0框架验证码功能实现方法【基于第三方扩展包】
2019/03/11 PHP
Laravel5.7 Eloquent ORM快速入门详解
2019/04/12 PHP
php定期拉取数据对比方法实例
2019/09/22 PHP
js最简单的拖拽效果实现代码
2010/09/24 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
从零学jquery之如何使用回调函数
2014/05/16 Javascript
Javascript中typeof 用法小结
2015/05/12 Javascript
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
浅谈JavaScript异常处理语句
2015/06/26 Javascript
两种JS实现屏蔽鼠标右键的方法
2020/08/20 Javascript
Bootstrap下拉菜单效果实例代码分享
2016/06/30 Javascript
Javascript基础学习笔记(菜鸟必看篇)
2016/07/22 Javascript
jquery 属性选择器(匹配具有指定属性的元素)
2016/09/06 Javascript
详细讲解JavaScript中的this绑定
2016/10/10 Javascript
jquery+Jscex打造游戏力度条
2020/09/12 Javascript
微信小程序自定义弹出层效果
2020/05/26 Javascript
跟老齐学Python之数据类型总结
2014/09/24 Python
Windows下的Python 3.6.1的下载与安装图文详解(适合32位和64位)
2018/02/21 Python
Python根据服务获取端口号的方法
2019/09/25 Python
python实现处理mysql结果输出方式
2020/04/09 Python
Jupyter Notebook的连接密码 token查询方式
2020/04/21 Python
小白教你PyCharm从下载到安装再到科学使用PyCharm2020最新激活码
2020/09/25 Python
Seavenger官网:潜水服、浮潜、靴子和袜子
2020/03/05 全球购物
一道Delphi上机题
2012/06/04 面试题
中西医结合临床医学专业大学生自荐信
2013/09/28 职场文书
机电专业毕业生推荐信
2013/11/10 职场文书
实习推荐信
2014/05/10 职场文书
商场营业员岗位职责
2015/04/14 职场文书
2016年校园重阳节广播稿
2015/12/18 职场文书
python opencv旋转图片的使用方法
2021/06/04 Python
详解Python+OpenCV进行基础的图像操作
2022/02/15 Python
Python实现批量将文件复制到新的目录中再修改名称
2022/04/12 Python