您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

23 个超实用 JS 技巧

时间:2021-09-27 13:01:19  来源:  作者:羲和时代

23 个超实用 JS 技巧

带有多个条件的 if 语句

把多个值放在一个数组中,然后调用数组的 includes 方法。

// bad
if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") {
//logic
}
// better
if (["abc", "def", "ghi", "jkl"].includes(x)) {
//logic
}

使用条件表达式简化 if true...else

// bad
let test: boolean;
if (x > 100) {
test = true;
} else {
test = false;
}
// better
let test = x > 10 ? true : false;
//或者这样
let test = x > 10;
console.log(test);

假值(undefined、null、0、false、NaN、空字符串)检查

当我们创建了新变量,有时候想要检查引用的变量是不是null 或 undefined空字符串 等假值。JAVAScript 确实有一个很好的快捷方式来实现这种检查-逻辑或操作符(||)

||会在左侧操作数为假值时返回右侧操作数

只有当左侧为:

  • 空字符串: ''或``
  • NaN
  • 0
  • null
  • undefined
  • false

逻辑或操作符(||) 会返回有右侧的值

// bad
if (test1 !== null || test1 !== undefined || test1 !== "") {
let test2 = test1;
}
// better
let test2 = test1 || "";
// bad
if (test1 === true) or if (test1 !== "") or if (test1 !== null)
// better
if (test1){
// do some
}else{
// do other
}

注意:如果 test1 有值,将执行 if 之后的逻辑,这个操作符主要用于 null,undefinded,空字符串 检查。

使用空值合并操作符-??

只有当左侧为

  • null
  • undefined

空值合并操作符(??) 会返回右侧的值

const baz = 0 ?? 42;
console.log(baz);
// expected output: 0

注意:与逻辑或操作符(||)不同,||会在左侧操作数为假值时返回右侧操作数

只有当左侧为:

  • 空字符串: ''或``
  • NaN
  • 0
  • null
  • undefined

逻辑或操作符(||) 会返回有右侧的值

var a = "" || 1;
// 输出 1
console.log(a);

null 检查和默认赋值

let test1 = null;
let test2 = test1 ?? "";
console.log("null check", test2); // 输出空字符串 ""

undefined 检查和默认赋值

const test = undefined ?? "default";
console.log(test);
// expected output: "default"

比较后返回

// bad
let test;
function checkReturn() {
if (!(test === undefined)) {
return test;
} else {
return callMe("test");
}
}
// better
function checkReturn() {
return test ?? callMe("test");
}

使用可选链操作符-?.

?. 也叫链判断运算符。它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个引用。当引用为空时,表达式停止计算并返回 undefined

const travelPlans = {
destination: "DC",
monday: {
location: "National Mall",
budget: 200,
},
};
// bad
const res =
travelPlans &&
travelPlans.tuesday &&

travelPlans.tuesday.location &&

travelPlans.tuesday.location.href;
// better
// 输出 undefined
const res1 = travelPlans?.tuesday?.location?.href;

用于多个条件判断的 && 操作符

如果只在变量为 true 时才调用函数,可以使用 && 操作符。

// bad
if (test1) {
callMethod();
}
// better
test1 && callMethod();

当你在 React 中想要有条件地渲染某个组件时,这个与 (&&)短路写法比较有用。例如:

<div> {this.state.isLoading && <Loading />} </div>

switch 简化

我们可以将条件保存在键值对象中,并根据条件来调用它们。

// bad
switch (data) {
case 1:
test1();
break;
case 2:
test2();
break;
case 3:
test();
break;
// And so on...
}
// better
var data = {
1: test1,
2: test2,
3: test,
};
// 如果type 在 data中存在, 则执行对应的函数
data[type] && data[type]();

默认参数值

// bad
function add(test1, test2) {
if (test1 === undefined) test1 = 1;
if (test2 === undefined) test2 = 2;
return test1 + test2;
}
// better
add = (test1 = 1, test2 = 2) => test1 + test2;
add(); //output: 3

条件查找简化

如果我们要基于不同的类型调用不同的方法,可以使用多个 else if 语句或 switch,但有没有比这更好的简化技巧呢?其实是前面的 switch 简化方式一样!

// bad
if (type === "test1") {
test1();
} else if (type === "test2") {
test2();
} else if (type === "test3") {
test3();
} else if (type === "test4") {
test4();
} else {
throw new Error("Invalid value " + type);
}
// better
var types = {
test1,
test2,
test3,
test4,
};
types[type] && types[type]();

对象属性赋值

let test1 = "a";
let test2 = "b";
// bad
let obj = { test1: test1, test2: test2 };
// better
let obj = { test1, test2 };

解构赋值

// bad
const test1 = this.data.test1;
const test2 = this.data.test2;
const test2 = this.data.test3;
// better
const { test1, test2, test3 } = this.data;

模板字符串

如果你厌倦了使用 + 将多个变量连接成一个字符串,那么这个简化技巧将让你不再头痛。

// bad
const welcome = "Hi " + test1 + " " + test2 + ".";
// better
const welcome = `Hi ${test1} ${test2}`;

跨行字符串

// bad
const data =
"abc abc abc abc abc abcnt" + "test test,test test test testnt";
// better
const data = `abc abc abc abc abc abc
test test,test test test test`;

indexOf 的按位操作简化

在查找数组的某个值时,我们可以使用 indexOf() 方法。但有一种更好的方法,让我们来看一下这个例子。

// bad
if (arr.indexOf(item) > -1) {
// item found
}
if (arr.indexOf(item) === -1) {
// item not found
}
// better
if (~arr.indexOf(item)) {
// item found
}
if (!~arr.indexOf(item)) {
// item not found
}

按位 (~) 运算符将返回 true(-1 除外),反向操作只需要!~。另外,也可以使用 includes() 函数。

if (arr.includes(item)) {
// true if the item found
}

字符串转成数字

有一些内置的方法,例如 parseInt 和 parseFloat 可以用来将字符串转为数字。我们还可以简单地在字符串前提供一个一元运算符 (+) 来实现这一点。

// bad
let total = parseInt("453");
let average = parseFloat("42.6");
// better
let total = +"453";
let average = +"42.6";

顺序执行 promise

如果你有一堆异步或普通函数都返回 promise,要求你一个接一个地执行,怎么办?

async function getData() {
const promises = [fetch("url1"), fetch("url2"), fetch("url3"), fetch("url4")];
for (const item of promises) {
// 打印出promise
console.log(item);
}
// better
for await (const item of promises) {
// 打印出请求的结果
console.log(item);
}
}

等待所有 promise 完成

Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例才会结束

有时候,我们不关心异步请求的结果,只关心所有的请求有没有结束。这时,Promise.allSettled()方法就很有用

const promises = [fetch("index.html"), fetch("https://does-not-exist/")];
const results = await Promise.allSettled(promises);
// 过滤出成功的请求
const successfulPromises = results.filter((p) => p.status === "fulfilled");
// 过滤出失败的请求,并输出原因
const errors = results
.filter((p) => p.status === "rejected")
.map((p) => p.reason);

交换数组元素的位置

// bad
const swapWay = (arr, i, j) => {
const newArr = [...arr];
let temp = newArr[i];
newArr[i] = list[j];
newArr[j] = temp;
return newArr;
};

ES6 开始,从数组中的不同位置交换值变得容易多了

// better
const swapWay = (arr, i, j) => {
const newArr = [...arr];
const [newArr[j],newArr[i]] = [newArr[i],newArr[j]];
return newArr;
};

使用变量作为对象键

当你有一个字符串变量,并想将其用作对象中的键以设置一个值时可以用它

let property = "a";
const obj = {
b: "b",
};
property = "name";
obj[property] = "这是A";
// {b: "b", name: "这是A"}
console.log(obj);

带有范围的随机数生成器

有时你需要生成随机数,但希望这些数字在一定范围内,那就可以用这个工具。

function randomNumber(max = 1, min = 0) {
if (min >= max) {
return max;
}
return Math.floor(Math.random() * (max - min) + min);
}

生成随机颜色

function getRandomColor() {
const colorAngle = Math.floor(Math.random() * 360);
return `hsla(${colorAngle},100%,50%,1)`;
}

获取列表最后一项

其他语言里这个功能被做成了可以在数组上调用的方法或函数,但在 JavaScript 里面,你得自己做点工作。

let array = [0, 1, 2, 3, 4, 5, 6, 7];
console.log(array.slice(-1)) >>> [7];
console.log(array.slice(-2)) >>> [6, 7];
console.log(array.slice(-3)) >>> [5, 6, 7];
function lastItem(list) {
if (Array.isArray(list)) {
return list.slice(-1)[0];
}
if (list instanceof Set) {
return Array.from(list).slice(-1)[0];
}
if (list instanceof Map) {
return Array.from(list.values()).slice(-1)[0];
}
}

图片懒加载

在懒加载的实现中,有两个关键的数值:一个是当前可视区域的高度,另一个是元素距离可视区域顶部的高度。

当前可视区域的高度, 在和现代浏览器及 IE9 以上的浏览器中,可以用 window.innerHeight 属性获取。在低版本 IE 的标准模式中,可以用
document.documentElement.clientHeight 获取,这里我们兼容两种情况:

const viewHeight = window.innerHeight || document.documentElement.clientHeight;

而元素距离可视区域顶部的高度,我们这里选用 getBoundingClientRect() 方法来获取返回元素的大小及其相对于视口的位置。对此 MDN 给出了非常清晰的解释:

该方法的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的 css 边框集合 。

DOMRect 对象包含了一组用于描述边框的只读属性——left、top、right 和 bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Lazy-Load</title>
<style>
.img {
width: 200px;
height: 200px;
background-color: gray;
}
.pic {
// 必要的img样式
}
</style>
</head>
<body>
<div class="container">
<div class="img">
// 注意我们并没有为它引入真实的src
<img class="pic" alt="加载中" data-src="./images/1.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/2.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/3.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/4.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/5.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/6.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/7.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/8.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/9.png" />
</div>
<div class="img">
<img class="pic" alt="加载中" data-src="./images/10.png" />
</div>
</div>
</body>
</html>
<script>
// 获取所有的图片标签
const imgs =
document.getElementsByTagName('img')
// 获取可视区域的高度
const viewHeight = window.innerHeight ||
document.documentElement.clientHeight
// num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出
let num = 0
function lazyload(){
for(let i=num; i<imgs.length; i++) {
// 用可视区域高度减去元素顶部距离可视区域顶部的高度
let distance = viewHeight - imgs[i].getBoundingClientRect().top
// 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
if(distance >= 0 ){
// 给元素写入真实的src,展示图片
imgs[i].src = imgs[i].getAttribute('data-src')
// 前i张图片已经加载完毕,下次从第i+1张开始检查是否露出
num = i + 1
}
}
}
// 监听Scroll事件
window.addEventListener('scroll', lazyload, false);
</script>

图片预加载

class PreLoadImage {
constructor(imgNode) {
// 获取真实的DOM节点
this.imgNode = imgNode;
}
// 操作img节点的src属性
setSrc(imgUrl) {
this.imgNode.src = imgUrl;
}
}
class ProxyImage {
// 占位图的url地址
static LOADING_URL = "xxxxxx";
constructor(targetImage) {
// 目标Image,即PreLoadImage实例
this.targetImage = targetImage;
}
// 该方法主要操作虚拟Image,完成加载
setSrc(targetUrl) {
// 真实img节点初始化时展示的是一个占位图
this.targetImage.setSrc(ProxyImage.LOADING_URL);
// 创建一个帮我们加载图片的虚拟Image实例
const virtualImage = new Image();
// 监听目标图片加载的情况,完成时再将DOM上的真实img节点的src属性设置为目标图片的url
virtualImage.onload = () => {
this.targetImage.setSrc(targetUrl);
};
// 设置src属性,虚拟Image实例开始加载图片
virtualImage.src = targetUrl;
}
}

ProxyImage 帮我们调度了预加载相关的工作,我们可以通过 ProxyImage 这个代理,实现对真实 img 节点的间接访问,并得到我们想要的效果。

https://www.ixiera.com



Tags:JS   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  Tags: JS  点击:(12)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  Tags: JS  点击:(23)  评论:(0)  加入收藏
前言前几天有粉丝在群里问了一个json文件处理的问题。看上去他只需要follower和ddate这两个字段下的对应的值。我们知道json是一种常见的数据传输形式,所以对于爬取数据的数...【详细内容】
2021-12-07  Tags: JS  点击:(40)  评论:(0)  加入收藏
作者:前端进阶者来源:前端进阶学习交流一、前言 我们经常在网页上 ,游戏界面加载时会看到加载进度条的效果,我们往往会以为这些加载进度条的效果,很难实现。今天教大家JS+CSS结合...【详细内容】
2021-11-05  Tags: JS  点击:(45)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  Tags: JS  点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  Tags: JS  点击:(58)  评论:(0)  加入收藏
利用JS的CryptoJS 3.x和PHP的openssl_encrypt,openssl_decrypt实现AES对称加密解密,由于需要两种语言对同一字符串的操作,而CryptoJS 的默认加密方式为“aes-256-cbc”,PHP端也...【详细内容】
2021-09-16  Tags: JS  点击:(79)  评论:(0)  加入收藏
作者:JShaman.com:w2sft内容预告:本文将实例讲解以下JS代码混淆加密技术:方法名转义和转码、成员表达式转IIFE、函数标准化、数值混淆、布尔型常量值混淆、二进制表达式转为调用...【详细内容】
2021-09-03  Tags: JS  点击:(81)  评论:(0)  加入收藏
Web 浏览器日益强大,网站和 Web 应用程序的复杂性也在增加。几十年前需要超级计算机的操作现在可以在智能手机上运行,其中之一就是人脸检测。检测和分析人脸的能力非常有用,因...【详细内容】
2021-08-20  Tags: JS  点击:(105)  评论:(0)  加入收藏
shell脚本是一个命令语言,面向的是操作系统执行。如果写过shell脚本的话,应该体会过编写过程的痛苦。因为shell并不是一个编程语言,并不支持常见的数组,JSON等数据结构,也不支持...【详细内容】
2021-08-09  Tags: JS  点击:(109)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(5)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(19)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(18)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(34)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(35)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(39)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== &#39;&#39;) { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(50)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条