写点什么

优雅编程 | javascript 代码优化的 15 个小知识

用户头像
devpoint
关注
发布于: 2021 年 03 月 08 日
优雅编程 | javascript代码优化的15个小知识

虽然已经和 javascript 打交道很长时间了,但有时可能没有更新最新的特性,这些特性可以解决日常的一些问题,而不需要编写额外的代码。


在这里,收集总结了编写优雅代码的经验,对代码优化及 review 有一定的帮助。

1、如何在 JavaScript 中检查空字符串/undefined/null?

判断一个变量是否为空字符串、undefined、null,在与后台 API 联调时特别常见。

!!data

const items = ["", null, undefined];for (const item of items) {    console.log(!!item);}
复制代码

使用类型转换 Boolean(data)

const items = ["", null, undefined];for (const item of items) {    console.log(Boolean(item));}
复制代码


两种方法实现了相同的功能,将变量类型转换为布尔值。


  • 对于nullundefined0000""false,它将返回false

  • 对于字符串"0" 和空格" ",它返回true

2、小数四舍五入

这里列举四种实现方式

parseFloat

parseFloat() 函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。


const FLOOR_NUMBER = 3.141592653;console.log(parseFloat(FLOOR_NUMBER).toFixed(2));   // 3.14
复制代码

Math.round

Math.round() 函数返回一个数字四舍五入后最接近的整数。


const FLOOR_NUMBER = 3.141592653;console.log(Math.round(FLOOR_NUMBER * 100 + Number.EPSILON) / 100);
复制代码


Number() 构造函数创建一个 Number 对象。

将字符串转换为十进制

const FLOOR_NUMBER = 3.141592653;const strNumber = FLOOR_NUMBER.toFixed(2); // => '3.14'console.log(Number(strNumber)); // => 3.14
复制代码

使用 Lodash

const _ = require("lodash");const FLOOR_NUMBER = 3.141592653;console.log(_.floor(FLOOR_NUMBER, 2));
复制代码

3、对象数组按照指定 key 排序

实现的方式有几种,这里列举三种供参考

使用 Lodash

Lodash 是一个一致性、模块化、高性能的 javascript 实用工具库,俗称下划线 _


_.sortBy(collection, [iteratees=[_.identity]])
复制代码


创建一个元素数组。 以 iteratee 处理的结果升序排序。 这个方法执行稳定排序,也就是说相同元素会保持原始排序。 iteratees 调用 1 个参数: (value)。


const _ = require("lodash");var users = [    { user: "fred", age: 48 },    { user: "barney", age: 36 },    { user: "fred", age: 40 },    { user: "barney", age: 34 },];
_.sortBy(users, function (o) { return o.user;}); // 结果为: [{ user: 'barney', age: 36 },{ user: 'barney', age: 34 },{ user: 'fred', age: 48 },{ user: 'fred', age: 40 }]
_.sortBy(users, ["user", "age"]); // 结果为: [{ user: 'barney', age: 34 },{ user: 'barney', age: 36 },{ user: 'fred', age: 40 },{ user: 'fred', age: 48 }]
_.sortBy(users, "user", function (o) { return Math.floor(o.age / 10);}); // 结果为: [{ user: 'barney', age: 36 },{ user: 'barney', age: 34 },{ user: 'fred', age: 48 },{ user: 'fred', age: 40 }]
复制代码

使用 ES6

var users = [    { user: "fred", age: 48 },    { user: "barney", age: 36 },    { user: "fred", age: 40 },    { user: "barney", age: 34 },];
// 按照age排序const result = users.sort(function (a, b) { return a.age - b.age;});console.log(result); // [{ user: 'barney', age: 34 }, { user: 'barney', age: 36 },{ user: 'fred', age: 40 },{ user: 'fred', age: 48 }]
复制代码

4、对象遍历

每个 ECMAScript 版本都采用不同的方式遍历对象。

ES5 可以使用以下方法

  • Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

  • forEach() 方法对数组的每个元素执行一次给定的函数


const myinfo = { name: "devpoint", city: "Shenzhen" };Object.keys(myinfo).forEach((key) => {    console.log(key, "=", myinfo[key]);}); 
复制代码

ES6 中可以使用 for...of

for...of语句在可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。


const myinfo = { name: "devpoint", city: "Shenzhen" };
for (const key of Object.keys(myinfo)) { console.log(key, "=", myinfo[key]);}
复制代码

ES8 使用Object.entries()

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。


Object.entries(myinfo).forEach(([key, value]) => console.log(key, "=", value));
复制代码


也可以这样:


for (const [key, value] of Object.entries(myinfo)) {    console.log(key, "=", value);}
复制代码

使用 Lodash

const _ = require("lodash");const myinfo = { name: "devpoint", city: "Shenzhen" };
_.forEach(myinfo, (value, key) => { console.log(key, "=", value);});
复制代码

5、event.stopPropagation()、event.preventDefault() 和 return false 区别

event.stopPropagation() 阻止事件的冒泡方法,不让事件向 documen上蔓延,但是默认事件任然会执行,当你掉用这个方法的时候,如果点击一个连接,这个连接仍然会被打开;


event.preventDefault() 阻止默认事件的方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;


return false 比较暴力,会同时阻止事件冒泡也会阻止默认事件;写上此代码,连接不会被打开,事件也不会传递到上一层的父元素;可以理解为return false就等于同时调用了event.stopPropagation() 和event.preventDefault()


$(".header a").click(function (e) {    event.stopPropagation(); //不会打印 devpoint ,但是页面会跳转;});$(".header").click(function () {    console.log("devpoint"); });
复制代码


$(".header").click(function () {    console.log("devpoint"); });$(".header a").click(function (e) {    event.preventDefault(); // 页面不会跳转,但会打印 devpoint;});
复制代码

6、如何获取当前 url

这是比较常见的,使用方法:window.location.href

7、如何判断对象是否存在某个 KEY?

如判断对象中是否存在键值:title

使用操作符

const info = {    title: "devpoint",};const detail = {    content: "Hello",};const find = "title";const result = find in info;const result2 = find in detail;console.log(result); // trueconsole.log(result2); // false
复制代码

使用hasOwnProperty

const info = {    title: "devpoint",};const detail = {    content: "Hello",};const find = "title";const result = info.hasOwnProperty(find);const result2 = info.hasOwnProperty(detail);console.log(result); // trueconsole.log(result2); // false
复制代码

直接读取 key 值

const info = {    title: "devpoint",};const detail = {    content: "Hello",};const find = "title";const result = info[find] !== undefined;const result2 = detail[find] !== undefined;console.log(result); // trueconsole.log(result2); // false
复制代码

8、 如何插入元素到数组指定索引位置?

在特定索引位置附加 1 个元素,这里讨论的问题排除头部和尾部的情况,如在索引为2后面插入元素devpoint


const items = ["info", "name", "age", "day"];const insertItem = "devpoint";items.splice(2, 0, insertItem);console.log(items); // [ 'info', 'name', 'devpoint', 'age', 'day' ]
复制代码


附加多个元素,也是适用的。


const items = ["info", "name", "age", "day"];const insert1 = "devpoint";const insert2 = "https";items.splice(2, 0, insert1, insert2);console.log(items); // [ 'info', 'name', 'devpoint', 'https', 'age', 'day' ]
复制代码


将 1 个数组所有元素附加到指定索引后面,如下:


const items = ["info", "name", "age", "day"];const news = ["devpoint", "https"];items.splice(2, 0, ...news);console.log(items); // [ 'info', 'name', 'devpoint', 'https', 'age', 'day' ]
复制代码

9、如何合并两个数组并删除重复项?

在开发中,合并数组并删除重复项是比较常见的需求。

使用 Lodash

const _ = require("lodash");const item1 = [2021, 2022, 2023];const item2 = [2019, 2020, 2021];const newItem = _.union(item1, item2);console.log(newItem); // [ 2021, 2022, 2023, 2019, 2020 ]
复制代码

使用数组方法filtercontact

const item1 = [2021, 2022, 2023];const item2 = [2019, 2020, 2021];
const tmpItem = item1.concat(item2); // [ 2021, 2022, 2023, 2019, 2020, 2021 ]const newItem = tmpItem.filter((val, pos) => tmpItem.indexOf(val) === pos); // [ 2021, 2022, 2023, 2019, 2020 ]
复制代码

使用set

const item1 = [2021, 2022, 2023];const item2 = [2019, 2020, 2021];
const newItem = [...new Set([...item1, ...item2])]; // [ 2021, 2022, 2023, 2019, 2020 ]
复制代码

10、如何在字符串中查找字符并替换为空?

使用replace

let str = "developpoint";const findStr = "elop";str = str.replace(findStr, ""); // devpointconsole.log(str);
复制代码

使用正则表达式

let str = "developpoint";const findStr = "elop";str = str.replace(new RegExp(findStr), "");
复制代码

11、如何在数组中追加新的元素?

在过去的 JavaScript 版本中,是通过使用apply方法来实现的。


const item1 = [2021, 2022, 2023];const item2 = [2019, 2020];
Array.prototype.push.apply(item2, item1);console.log(item2); // [ 2019, 2020, 2021, 2022, 2023 ]
复制代码

使用 ES6

const item1 = [2021, 2022, 2023];const item2 = [2019, 2020];
item2.push(...item1);console.log(item2); // [ 2019, 2020, 2021, 2022, 2023 ]
复制代码

12、如何判断一个对象是否为数组?

判断一个对象是否为数组,使用场景也是比较常见的,同样可以使用Lodash,这里不做详细介绍了,有兴趣可以去看看文档


在 ES6 之前的版本可以通过下面的方式来判断是否为数组(可以兼容旧的浏览器),为了方便,三种方式写在一起。


const arrayYears = [2021, 2022, 2023];const objYears = { value: "2021" };
const isArray = (() => { return { byInstanceof: (array) => { return array instanceof Array; }, byConstructor: (array) => { return array.constructor.toString().indexOf("Array") > -1; }, byPrototype: (array) => { return Object.prototype.toString.call(array) === "[object Array]"; }, };})();
console.log(isArray.byInstanceof(arrayYears)); // trueconsole.log(isArray.byConstructor(arrayYears)); // trueconsole.log(isArray.byPrototype(arrayYears)); // true
console.log(isArray.byInstanceof(objYears)); // falseconsole.log(isArray.byConstructor(objYears)); // falseconsole.log(isArray.byPrototype(objYears)); // false
复制代码

使用 ES6

使用 ES6 就简洁多了。


const arrayYears = [2021, 2022, 2023];const objYears = { value: "2021" };
const isArray = (array) => { return Array.isArray(array);};console.log(isArray(arrayYears)); // trueconsole.log(isArray(objYears)); // false
复制代码

13、如何解析 URL 中的参数?

当在处理 URL 的时候,经常遇到需要解析 URL 中的参数,并获取其值。

使用正则

const getQueryStringParams = (query) => {    return query        ? (/^[?#]/.test(query) ? query.slice(1) : query)              .split("&")              .reduce((params, param) => {                  const [key, value] = param.split("=");                  params[key] = value                      ? decodeURIComponent(value.replace(/\+/g, " "))                      : "";                  return params;              }, {})        : {};};const params = getQueryStringParams("?wd=devpoint"); // { wd: 'devpoint' }console.log(params); // { wd: 'devpoint' }
复制代码

使用 URLSearchParams

URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。拥有包括appenddeleteentries等方法,详见介绍


const getQueryStringParams = (strUrl) => {    return new URL(strUrl).searchParams;};const url = "https://www.baidu.com/s/?wd=devpoint";const params = getQueryStringParams(url); // URLSearchParams { 'wd' => 'devpoint' }console.log(params.get("wd")); // devpoint
复制代码

14、如何获取对象的长度(key 数量)?

大部份情况下,我们会检查数组的长度,但如果要获取对象的长度呢?下面两种方法是获取对象长度的最佳方法。

使用 Lodash

const _ = require("lodash");const obj = {    title: "devpoint",    city: "Shenzhen",    type: "blog",};const objSize = _.size(obj);console.log(objSize); // 3
复制代码

使用 ES6

const obj = {    title: "devpoint",    city: "Shenzhen",    type: "blog",};const objSize = Object.keys(obj).length;console.log(objSize); // 3
复制代码

15、如何将字符串转换为对象数组?

当从无法控制的第三方 API 获取一些数据时,就会出现这种情况。如何将字符串转换为对象数组以在应用程序中更好的使用?以下是获得此结果的最简单方法。


const apiData = "Option 1|false|Option 2|false|Option 3|false|Option 4|true";
const formatToArray = (str) => { return str.split("|").reduce((arrayResult, item, index, arrData) => { if (index % 2 === 0) { const [option, value] = [item, JSON.parse(arrData[index + 1])]; arrayResult.push({ option, value }); } return arrayResult; }, []);};console.log(formatToArray(apiData));
复制代码

输出的数据格式为:

[  { option: 'Option 1', value: false },  { option: 'Option 2', value: false },  { option: 'Option 3', value: false },  { option: 'Option 4', value: true }]
复制代码

javascript 的灵活性,使得编写优雅的代码方法多种多样,需要去深入研究并总结,今天的分享就到此。


发布于: 2021 年 03 月 08 日阅读数: 16
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
优雅编程 | javascript代码优化的15个小知识