42个实用的JavaScript优化技巧
英文 | https://javascript.plainenglish.io/42-tips-and-tricks-to-write-faster-better-optimized-javascript-code-3a82c53d051e
翻译 | web前端开发
我一直喜欢报纸之类的东西,可以在较短的时间内提供足够的信息。在这里,我为前端开发优化创建了一个新的学习列表。
你可能已经进行了很长时间的JavaScript开发,但是,有的最新功能与开发技巧,你可能没有使用过。今天这篇文章就是帮助你解决一些JavaScript中的新问题新技巧。
在这里,我分享了42个技巧,这些技巧对我的日常开发编程工作很有帮助,也希望这些技巧对你也有所帮助。
1、按字符串属性值对对象数组进行排序
可以通过不同的方式来完成。
1)、使用Underscore
_.sortBy(collection, [iteratees=[_.identity]])
创建一个元素数组,并按照在每个Iteratee中运行集合中每个元素的结果,以升序排序。此方法执行稳定的排序,即保留相等元素的原始排序顺序。迭代对象由一个参数(value)调用。
var objs = [
{ val1: 'abc',val2: 'a' },
{ val1: 'cde', val2: 'b' },
{ val1: 'fgh', val2: 'c' }
];
var sortedValues = _.sortBy( objs, 'val1' );
2)、使用ES6排序功能
var data = [
{ name: 'abc', value: 21 },
{ name: 'cde', value: 37 },
{ name: 'ee', value: 45 },
{ name: 'ff', value: -12 },
{ name: 'ab', value: 13 },
{ name: 'cs', value: 37 }
];
// sort by value
data.sort(function (a, b) {
return a.value - b.value;
});
3)、使用Lodash
const sortedValues = _.sortBy(data, 'string');
2、如何四舍五入至小数点后两位(仅在必要时)?
我们可以通过3种不同的方式来实现此功能。
在跳转到解决方案之前,让我们先了解一些定义。
该parseFloat()函数解析一个参数(如果需要,首先将其转换为字符串)并返回一个浮点数。
该toFixed()方法使用定点表示法格式化数字。
1)、使用ParseFloat
parseFloat("183.456").toFixed(2);
该Math.round()函数返回四舍五入到最接近的整数的数字的值。
2)、使用MathRound
Math.round( num * 100 + Number.EPSILON ) / 100
Number()创建一个新Number值。
3)、将字符串转换为十进制
var string = 10.134.toFixed(2); // => '10.13'
var num = Number(string); // => 10.13
3、如何遍历或枚举JavaScript对象?
每个ECMAScript版本都采用不同的方式枚举对象。让我们检查一下。
该Object.keys()方法返回给定对象自己的可枚举属性名称的数组,并以与普通循环相同的顺序进行迭代。
该forEach()方法为每个数组元素执行一次提供的功能。
ES5(Object.keys()和forEach)
var data = { val1: "abc", val2: "cde" };
Object.keys(data).forEach(function(key) {
console.log(key, obj[key]);
});
ES6(for ... of):
该for...of语句在创建了一个循环迭代迭代的对象,包括:内置String,Array,阵列状物体(例如,arguments或NodeList), TypedArray,Map,Set和用户定义的iterables。它使用对象的每个不同属性的值调用要执行的语句来调用自定义迭代挂钩。
for (const key of Object.keys(data)) {
console.log(key, obj[key]);
}
ES8 Object.entries()
该Object.entries()方法返回给定对象自己的可枚举字符串键属性[key, value]对的数组,其顺序与for...in循环提供的顺序相同。
Object.entries(data).forEach(
([key, value]) => console.log(key, value)
);
我们可以合并for...of,销毁和Object.entries:
for (const [key, value] of Object.entries(data)) {
console.log(key, value);
}
4、event.preventDefault()和return false有什么区别?
如果返回false,则有可能正在执行其他函数,这些函数是专门在click内编写的,而preventDefault则不允许执行任何操作。
$('a').click(function (e) {
// logic
// runtime error...navigation happened
return false;
});
preventDefault()的示例
$('a').click(function (e) {
e.preventDefault();
// logic
// runtime error, naviagation will not happen
});
5、如何检查JavaScript中的空字符/未定义字符串/空字符串?
if (!!data) {
// Some code here
}
或使用类型转换:
if (Boolean(data)) {
// Code here
}
两者执行相同的功能。将变量类型转换为布尔值,其中str是变量。
对于null,undefined,0、000,“ ”,false,它将返回false。
对于字符串“ 0”和“空格 ”,它返回true。
6、如何将项目插入到特定索引(JavaScript)的数组中?
在特定索引处附加单个元素
//Append at index 2
array.splice(2, 0,'newData');
//Append at index 5
array[5] = 'newData';
在特定索引处附加多个元素。
//Append at index 2
array.splice(2, 0,'data1', 'data2', 'data3');
7、如何使用JavaScript获取当前URL?
使用windows功能:window.location.href
8、检查密钥是否存在于JavaScript对象中?
在操作符中使用。
let data =“ abc” in array;
使用hasOwnProperty
let result = data.hasOwnProperty("abc")
直接访问元素(括号样式)
let result = data["abc"] === undefined
直接访问元素(对象样式)
let result = array.abc === undefined;
9、如何在JavaScript中合并两个数组并删除重复项?
我们确实在日常生活中使用数组,并且有很多要求,我们需要组合数组以及删除重复项。
以下是实现此目的的一些方法。
1)、使用Lodash
console.log(_.union([10, 4, 5], [134, 26, 19, 10], [6, 1]));
2)、使用Filter和Concat
let a = [56, 43, 3], b = [11, 43, 56, 12]
let c = a.concat(b)
let d = c.filter((val, pos) => c.indexOf(val) === pos)
3、使用set
[...new Set([...array1 ,...array2])]; // => remove duplication
10、如何检查字符串在JavaScript中是否包含子字符串?
我们可以使用以下两种方法来实现此功能。
1)、includes()
该includes()方法确定一个数组是否在其条目中包括某个值,是返回值true还是false适当的值。
const val1 = "atitpatel";
const val2 = "patel";
console.log(string.includes(val2));
2)、indexof()
在indexOf()该方法返回在该给定元素可以在阵列中可以发现,或-1,如果它不存在的第一个索引。
var str = "atitpatel";
var substr = "patel";
console.log(str.indexOf(substr) !== -1);
11、如何替换所有出现的字符串
1)、我们可以使用ES6来解决这个问题。
str = str.replace(/test/g, '');
2)、我们可以使用正则表达式。
let find = 'ab';
let re = new RegExp(find, '');
let str = find.replace(re, 'cd');
console.log(str);
12、如何正确克隆JavaScript对象
1)、使用ES6
var val1 = {data: "value"};
var val2= Object.assign({}, val1);
2)、如果要浅拷贝
Object.assign({}, data)
3)、进行深复制
JSON.parse(JSON.stringify(data))
13、!!不是JavaScript中的运算符?
!! 将其右侧的值转换为其等效的布尔值。
!!false === false
!!true === true
!!0 === false
!!parseInt("foo") === false // NaN is falsy
!!1 === true
!!-1 === true // -1 is truthy
!!(1/0) === true // Infinity is truthy
!!"" === false // empty string is falsy
!!"foo" === true // non-empty string is truthy
!!"false" === true // ...even if it contains a falsy value
!!window.foo === false // undefined is falsy
!!null === false // null is falsy
!!{} === true // an (empty) object is truthy
!![] === true // an (empty) array is truthy;
14、如何在JavaScript中循环遍历数组?
我们有几种选择:
1)、顺序for循环:
var array = ["a","b"];
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
console.log("value",array[i]);
}
2)、Array.prototype.forEach
const data = ["a", "b", "c"];
data.forEach(function (item, index) {
console.log(item, index);
});
3)、 ES6for-of声明
let data = ['a', 'b', 'c'];
for (const a of data){
console.log(a);
}
15、如何使用JavaScript复制到剪贴板
通过执行以下操作,我们可以提示用户单击并输入:
function copy(text) {
window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}
现在,剪贴板复制操作为SAFE,因为用户单击了提示。
<button id="data" onclick="copy(document.getElementById('data').innerHTML)">Copy here</button>
<script>
function copy(text) {
window.prompt("To Copy Please do this: Ctrl+C, Enter", text);
}
</script>
16、如何测试一个空的JavaScript对象
有几种方法可以实现此功能。
1)、jQuery的:
jQuery.isEmptyObject({}); // true
2)、 lodash:
_.isEmpty({}); // true
3)、Underscore
_.isEmpty({}); // true
17、如何在JavaScript中使字符串的首字母大写
我们可以更新具有text-transform属性的CSS。
1)、在CSS中:
p:first {
text-transform:capitalize;
}
2)、使用函数,我们可以调用toUpperCase()方法。
function makeUpperCase(val)
{
return val && val[0].toUpperCase() + val.slice(1);
}
18、如何使用JavaScript更改元素的类?
有很多需求,我们需要根据条件更改某些颜色或CSS。
如何在JavaScript中完成?
更改元素的所有类:
要将所有现有类替换为一个或多个新类,请设置className属性:
document.getElementById("test").className = "newclass";
要将其他类添加到元素:
要将类添加到元素中而不删除或影响现有值,请添加空格和新的类名称,如下所示:
document.getElementById("test").className += " newClass";
要从元素中删除类:
要在元素中删除单个类而又不影响其他潜在类,则需要简单的正则表达式替换:
document.getElementById("test").className =
document.getElementById("test").className.replace
( /(?:^|\s)newClass(?!\S)/g , '' )
19、是否可以将CSS应用于一半的字符?
我们确实看到了一些精美的文字艺术,其中一半字符具有不同的颜色,而另一半字符具有不同的颜色,我们如何在CSS中实现这样的效果?
下面是使CSS适用于半角字符的示例。
h1 {
display: inline-block;
margin: 0; /* for demo snippet */
1em; /* for demo snippet */ :
helvetica, arial, sans-serif; :
bold; :
300px; :
background: linear-gradient(to right, #7db9e8 50%,#1e5799 50%);
text; :
transparent; :
}
<h1>XYZ</h1>
20、如何在数组中追加内容?
在较早的JavaScript版本中,这是通过使用apply方法完成的。
该apply()方法调用具有给定this值的函数,并arguments以数组(或类似数组的对象)的形式提供。
let array1 = [33, 45, 5];
let array2 = [100, 2];
Array.prototype.push.apply(array2, array1);
console.log(array2); // [100, 2, 33, 45, 5]
使用ES6,可以使用扩展运算符完成此操作。
let array1 = [11, 42, 53];
let array2 = [1, 2];
array2.push(...array1);
console.log(array2); // [11, 2, 3, 42, 53]
21、如何检查对象是否为数组?
当我们想检查对象是否为数组时,可以遵循以下选项。
let arr = [10,20,30,40,50];
Javascript(新旧浏览器):
function isArray(arr) {
return arr.constructor.toString().indexOf("Array") > -1;
}
function isArray(arr) {
return arr instanceof Array;
}
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
然后这样称呼它:
isArray(arr);
JavaScript(IE9 +,Ch5 +,FF4 +,Saf5 +,Opera10.5 +)
Array.isArray(arr);
下划线和Lodash:
_.isArray(arr);
22、如何检测未定义的对象属性?
当我们想检查对象的特定属性是否未定义时,我们可以直接使用if条件和===运算符进行检查。
if(data.prop === undefined) {
alert("it is: `undefined`");
}
要检查对象是否实际上没有这样的属性,并尝试访问它时,默认情况下将返回undefined:
if(!o.hasOwnProperty('prop')) {
alert("not exisiting);
}
检查与标识符关联的值是否为特殊值undefined,或者尚未声明该标识符。
if(typeof variable === 'undefined') {
alert('variable is `undefined`, or it is not declared');
}
23、如何在JavaScript中将字符串转换为布尔值?
有几种方法可以在JavaScript中将字符串转换为布尔值。
使用测试方法
var stringValue = "true";
var boolValue = (/true/i).test(stringValue) //returns true
使用比较运算符
var val = "true";
var boolValue = (val =="true"); //returns true
使用JSON.parse
var val = "true";
var boolValue = JSON.parse(val); //returns true
使用三元运算符
var val = “true”;
var boolValue = val.toLowerCase() == ‘true’ ? true : false; //returns true
使用 switch-case
var val = "true";
var boolValue = getBoolean(val); //returns true
function getBoolean(value){
switch(value){
case true:
case "true":
case 1:
case "1":
case "on":
case "yes":
return true;
default:
return false;
}
}
24、如何获取JavaScript中的查询字符串值?
当我们处理URL参数并想从URL中提取信息时,这是最常见的用法。
下面是一些我们可以从中获取字符串值的方法。
ES2015(ES6):创建一种实现此功能的方法
getQueryStringParams = query => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split('&')
.reduce((params, param) => {
let [key, value] = param.split('=');
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
return params;
}, {}
)
: {}
};
URLSearchParams从位置使用内置方法。
你可以在location以下位置使用它:
let params = new URLSearchParams(location.search);
let params = (new URL(location)).searchParams;
let url = new URL('https://abc.com?val1=1&val2=2');
let params = new URLSearchParams(url.search);
我们还可以使用.searchParamsURL对象的简写属性来获取参数,如下所示:
let params = new URL('https://abc.com?val1=1&val2=2').searchParams;
params.get('val1'); // "1"
params.get('val2'); // "2"
25、如何获取JavaScript对象的长度?
在大多数情况下,我们确实检查数组的长度,但是,如果要检查对象的长度怎么办?以下两种方法是获取对象长度的最佳方法。
1、使用ES6功能
let size = Object.keys(data).length;
2、使用下划线
_.size({val1 : 1, val2 : 2, val3 : 3});
26、如何反转包含复杂表情符号的字符串?
当我们进行更多编程或遇到一些编码挑战时,这是其中最常见的问题。
我们可以使用lodash功能来解决这一挑战。
function reverse(txt) { return _.split(txt, '').reverse().join(''); }
const data = 'abc abc👩🦰👩👩👦👦';
console.log(reverse(data));
27、如何在JavaScript中将字符串转换为对象数组?
当我们从无法控制的第三方API中获取一些数据时,就会出现这种情况。我们如何将字符串转换为对象数组以在我们的应用程序中使用?下面是实现此结果的最简单方法
const str = 'Option 1|false|Option 2|false|Option 3|false|Option 4|true';
data = [];
for (let i = 0, a= str.split('|'); i < a.length; i += 2) {
const
option = a[i],
value = JSON.parse(a[i + 1]);
data.push({ option, value });
}
console.log(data);
28、如何检测用户是否更改了JavaScript中的选项卡?
这可以通过JavaScript支持的最新事件侦听器功能来实现。
下面是处理选项卡状态的解决方案。
document .addEventListener("visibilitychange", event => {
if (document.visibilityState == "visible") {
console.log("activated")
} else {
console.log("inactivated")
}
})
29、如何从一个对象数组求和一个属性值?
当我们有一个包含一些数字的对象数组时,我们想在下面求和是带有reduce的解决方案。
const data = [
{ val1: 'abc', val2: 50 },
{ val1: 'abc', val2: 50 },
{ val1: 'cde', val2: 75 },
{ val1: 'hji', val2: 35 },
{ val1: 'bbc', val2: 25 },
];
console.log(data.reduce((n, {val2}) => n + val2, 0))
30、如何格式化JavaScript日期?
当我们格式化日期时,更令人头疼,因为我们确实根据需求有不同的要求。我们如何才能满足每个人的需求?以下是广泛用于在JavaScript中格式化日期的最常用方法。
1)、你可以使用本机 .toLocaleDateString()
例子:
new Date().toLocaleDateString() // 1/06/2021
new Date().toLocaleDateString('en-US', {year: 'numeric', month: '2-digit', day: '2-digit'}); // 01/06/2021 (month and day with two digits)
new Date().toLocaleDateString('en-ZA'); // 2020/01/06(year/month/day) notice the different locale
new Date().toLocaleDateString('en-CA'); // 2021-01-06 (year-month-day) notice the different locale
new Date().toLocaleString("en-US", {hour: '2-digit', hour12: false, timeZone: "America/New_York"}); // 07 (just the hour)
2)、我们可以使用moment.js
var now = new Date();
var dateString = moment(now).format('YYYY-MM-DD');
var dateStringWithTime = moment(now).format('YYYY-MM-DD HH:mm:ss');
31、如何在JavaScript中生成随机字符串/字符?
很多时候,我们需要向后端发送一些随机的唯一ID。实现此功能的解决方案有成千上万种,但以下是我最喜欢的一种。
生成一个安全的随机字母数字Base-62字符串:
function generateUID(length)
{
return window.btoa(Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2))).map((b) => String.fromCharCode(b)).join("")).replace(/[+/]/g, "").substring(0, length);
}
console.log(generateUID(22)); // "cFg3Upv2cE5cK8Xd7hHwWp"
console.log(generateUID(5)); // "CAGkP"
32、在字段中输入3个字符后如何执行API调用?
当我们要搜索用户名或某个已经存在的值但又要避免一直调用时,我们经常要等到用户键入某些字符后再调用API,这是最常用的方法。
这可以使用distinctUntilChanged来实现,并且你可以使用filter。
this.service.getData(data)
.pipe(
filter(_ => data.length === 3),
distinctUntilChanged()
).subscribe(rs => console.log(rs));
33、如何重命名数组内的对象键?
有时我们需要更改键来操作数据。这是在数组中重命名对象键的有效方法之一。
你可以使用Object.values()它来检索值,然后array.reduce()组成一个新的对象:
const data = [{
prop_name: 'test1',
prop_age: 45,
prop_email: 'test1@test.com',
},
{
prop_name: 'test2',
prop_age: 41,
prop_email: 'test2@test.com',
},
{
prop_name: 'test3',
prop_age: 45,
prop_email: 'test3@test.com',
},
];
const newKey = [
'firstname',
'age',
'email'
];
let resultData = data.map(obj =>
Object.values(obj).reduce((acc, cur, i) => {
acc[newKey[i]] = cur;
return acc;
}, {}));
console.log(resultData);
34、如何清除javascript中的焦点?
焦点…焦点…是的,这一次,我们想从HTML中的特定元素中清除焦点。这可以通过模糊方法来实现。
if (document.activeElement instanceof HTMLElement)
document.activeElement.blur();
35、JavaScript中的二进制到字符串
如果我们有一些二进制代码,并且想要在将其用于代码之前将其转换为字符串,该怎么办?可以使用fromCharCode方法实现。
let binary = `1010011 1110100 1100001 1100011 1101011
1001111 1110110 1100101 1110010 1100110
1101100 1101111 1110111`;
let newData = binary.split(' ') //Split string in array of binary chars
.map(bin => String.fromCharCode(parseInt(bin, 2))) //Map every binary char to real character
.join(''); //Join the array back to a string
console.log(newData);
36、移位字符串在JavaScript中向左和向右循环
这种javascript编码问题很常见。这是基于给定值移动字符串的示例。可以使用数组切片方法来实现。
function getShiftedString(s, leftShifts, rightShifts) {
// using `split('')` will result in certain unicode characters being separated incorrectly
// use Array.from instead:
const arr = Array.from(s);
const netLeftShifts = (leftShifts - rightShifts) % arr.length;
return [...arr.slice(netLeftShifts), ...arr.slice(0, netLeftShifts)]
.join('');
}
console.log([
getShiftedString('abc', 0, 0),
getShiftedString('abc', 1, 0),
getShiftedString('abc', 0, 1),
getShiftedString('abc', 1, 1),
getShiftedString('123456789', 0, 0),
getShiftedString('123456789', 1, 5),
getShiftedString('123456789', 5, 1),
'----',
getShiftedString('123456789', 9, 0),
getShiftedString('123456789', 10, 0),
getShiftedString('123456789', 0, 9),
getShiftedString('123456789', 0, 10),
getShiftedString("🐎👱❤", 0, 0),
getShiftedString("🐎👱❤", 1, 0),
]);
37、检查IP地址的正则表达式JavaScript
正则表达式可帮助我们检查任何特定的字符串并为我们验证?如果我们要使用正则表达式作为IP地址该怎么办。我在这里喜欢Mahdi Pedram解决方案来实现这一目标。
这是验证IP地址的最干净的方法,下面将其分解:
事实:一个有效的IP地址具有4 octets,每个八位字节可以是一个介于0 - 255
正则表达式的细分,该正则表达式匹配之间的任何值 0 - 255
25[0-5] matches 250 - 255
2[0-4][0-9] matches200 - 249
1[0-9][0-9] matches 100 - 199
[1-9][0-9]? matches 1 - 99
0 matches 0
const octet = '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)';
注意:使用new RegExp时应使用\\.而不是\.因为字符串将被转义两次。
function isValidIP(str) {
const octet = '(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)';
const regex = new RegExp(`^${octet}\\.${octet}\\.${octet}\\.${octet}$`);
return regex.test(str);
}
38、如何用JSON对JavaScript日期进行字符串化并保留时区
当我们要将任何特定的日期格式值存储到JSON时。使用此功能可以实现。
var changeValue = function(key, value) {
if (this[key] instanceof Date) {
return this[key].toUTCString();
}
return value;
}
console.log(JSON.stringify(new Date(), changeValue));
console.log(JSON.stringify({ myProperty: new Date()}, changeValue));
39、JavaScript检查字符串是否为有效数字
我们已经看到了很多解决方案来检查数字是否有效,但是如果要检查字符串是否是有效数字怎么办?
这是最好的方法。
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
以下是一些很好的测试用例:
console.log(isNumeric(123456898898912345678912)); // true
console.log(isNumeric('2 ')); // true
console.log(isNumeric('-42.2 ')); // true
console.log(isNumeric(-562.2)); // true
console.log(isNumeric(undefined)); // false
console.log(isNumeric('')); // false
console.log(isNumeric(null)); // false
console.log(isNumeric([])); // false
40、将JSON对象导出到文本文件
当我们要将JSON对象导出到文本文件时,以下是我从NutCracker答案中发现的最干净的方法。
const filename = 'data.json';
const jsonStr = JSON.stringify(JsonExport);
let element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(jsonStr));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
41、将长模板文字行换行为多行,而不在字符串中创建新行
如果您在文字中新行的点处引入换行符(\),则不会在输出中创建新行:
const text = `abc abc abc abc abc abc abc\
and abc and abc`;
console.log(text);
42、如何将文本从div复制到剪贴板
当我们要将文本从div复制到下面的剪贴板时,这是我从StackOverflow romin21答案中找到的最简单的方法。
function CopyToClipboard(containerid) {
if (window.getSelection) {
if (window.getSelection().empty) { // Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) { // Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) { // IE?
document.selection.empty();
}
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select().createTextRange();
document.execCommand("copy");
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().addRange(range);
document.execCommand("copy");
}
}
到这里,我分享的42个JavaScript的技巧就全部结束了,希望,这个对你有所帮助。
感谢你的阅读,编程愉快!