主题
JS 实用技巧和注意事项
判断一个元素是否能在数组里找到
使用 _.some
而不是 _.find
, 因为 _.find 找到的元素有可能是 0
或者 false
或则 ''
, 从而造成 bug
javascript
var arr = [0, 1, 2];
if (_.find(arr, (item) => item === 0)) {
// 返回0, 所以找不到
console.log("找到了");
}
// 改成
if (_.some(arr, (item) => item === 0)) {
console.log("找到了");
}
react 根据条件渲染元素的时候
不要用 _.size
, 因为当元素为空时, 就会渲染出 0; 使用 _.isEmpty
去判断;
javascript
// react
render(){
const arr = [];
return {_.size(arr) && <div>title</div>} // 渲染出0
}
// react
render(){
const arr = [];
return {!_.isEmpty(arr) && <div>title</div>}
}
lodash 对于 string 没有 _.indexOf
方法
使用_.includes
, 而_.indexOf
是数组的方法
js
_.chain("11ab22").includes("ab").value(); // 返回 true
另外 _.startsWith
, 可以判断是否以某个字符串开头;
js
_.startsWith("abc", "a"); // true
_.startsWith("abc", "b"); // false
_.truncate
可用来添加省略号。
js
// 返回 h....
_.truncate("hello", {
length: 4
});
字母转为大小写
转换大写, 使用 _.toUpper
而不是 _.upperCase
, 转换小写, 使用 _.toLower
而不是 _.lowerCase
js
_.toUpper("--foo-bar--");
// => '--FOO-BAR--'
_.upperCase("--foo-bar");
// => 'FOO BAR'
_.toLower("--Foo-Bar--");
// => '--foo-bar--'
_.lowerCase("--Foo-Bar--");
// => 'foo bar'
模版字符串
如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!
javascript
function getPersonInfo(one, two, three) {
console.log(one); // ["", " is ", " years old", raw: ["", " is ", " years old"] ]
console.log(two); // Lydia
console.log(three); // 21
}
var person = "Lydia";
var age = 21;
getPersonInfo`${person} is ${age} years old`;
字符串当作对象的属性
javascript
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]); // 输出 456
试图将一个对象设置为对象的键值, 那么 这个 key 会转换成 "[object Object]"
, 所以上面的代码 a[b]
就相当于 a["[object Object]"]
, a[c]
相当于 a["[object Object]"]
, a[c]
会覆盖 a[b]
JS 哪些值是假值?
- undefined
- null
- NaN
- 0
- '' (empty string)
- false
JavaScript 中的所有内容都是?
原始或对象
原始数据类型和基本数据类型一个意思;
JavaScript 中共有 6 种基本数据类型:Undefined、Null、Boolean、Number、String、Symbol
对象类型有: Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型
[..."Lydia"]
返回什么?
返回 ["L", "y", "d", "i", "a"]
解构
多次解构, 就可以拿到 part 的值。
js
const obj = {
part: {
name: "David",
age: 37
}
};
const {
part: { name, age },
part
} = obj;
数字分隔符
数字分隔符是在 ECMAScript 2021(ES12)
, Chrome 75
版本就开始支持了。
js
const myMoney = 1_000_000_000_000;
// 等价于
const myMoney = 1000000000000;
生成随机字符串
Math.random()
生成随机数 0.6142088877102427
, toString(36)
转换成 36 进制 0.m40j2pdqw8o
, substr(2,10)
进行字符串截取。
js
const str = Math.random().toString(36).substr(2, 10);
console.log(str); // 'm40j2pdqw8'
使用 while 简写循环
下面的代码输出 1, 2, 3
js
var i = 0;
while (i++ < 3) {
console.log(i);
}
// 相当于
var i = 0;
while (i < 3) {
i++;
console.log(i);
}
Array.includes 判断多个 if 条件
js
//Longhand
if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") {
//logic
}
//Shorthand
if (["abc", "def", "ghi", "jkl"].includes(x)) {
//logic
}
三元运算符实现短函数调用
js
// Longhand
function test1() {
console.log("test1");
}
function test2() {
console.log("test2");
}
var test3 = 1;
if (test3 == 1) {
test1();
} else {
test2();
}
// Shorthand
(test3 === 1 ? test1 : test2)();
比较大小使用 a - b > 0 的方式更好,用 a > b 有时候会出现错误
js
// 错误用法
"20" > "100"; // true
// 预期结果
"20" - "100" > 0; // false
for...of 和 for... in
for...of
遍历可迭代对象, 比如 String, Array, Map, Set; 返回这些对象的值;
for...in
遍历普通对象, 遍历的时候还会返回 原型上的属性, 需要通过 hasOwnProperty 进行判断;
switch 语句优化成用字典的形式
js
let notificationPtrn;
switch (notification.type) {
case "citation":
notificationPtrn = "You received a citation from {{actingUser}}.";
break;
case "follow":
notificationPtrn = "{{actingUser}} started following your work";
break;
case "mention":
notificationPtrn = "{{actingUser}} mentioned you in a post.";
break;
default:
// Well, this should never happen
}
优化成:
js
const textOptions = {
citation: "You received a citation from {{actingUser}}.",
follow: "{{actingUser}} started following your work",
mention: "{{actingUser}} mentioned you in a post."
};
function getNotificationPtrn(textOptions, n) {
return textOptions[n.type];
}
const notificationPtrn = getNotificationPtrn(textOptions, notification);
链式取值 a[0].b 不存在的 undefined 问题
js
var obj = {
a: {
b: [1, 2, 3, 4]
},
a1: 121,
a2: "name"
};
let { b: result = "default" } = obj; // result: 'default'
string 强制转换为数字
可以用*1; 使用Number.isNaN
来判断是否为 NaN, 或者使用 a !== a
来判断是否为 NaN
js
"32" * 1; // 32
"ds" * 1; // NaN
null * 1; // 0
undefined * 1; // NaN
1 * { valueOf: () => "3" }; // 3
常用:也可以使用+来转化字符串为数字
js
+"123" + // 123
"ds" + // NaN
"" + // 0
null + // 0
undefined + // NaN
{ valueOf: () => "3" }; // 3
使用 filter 过滤数组中的所有假值
js
const compact = (arr) => arr.filter(Boolean);
compact([0, 1, false, 2, "", 3, "a", "e" * 23, NaN, "s", 34]);
取整 | 0
js
1.3 |
(0 - // 1
1.9) |
0; // -1
判断奇偶数 & 1
js
const num = 3;
!!(num & 1); // true
!!(num % 2); // true
强制参数,缺失报错
js
logError = () => {
throw new Error("Missing parameter!");
};
foo = (bar = logError()) => {
// 这里如果不传入参数,就会执行logError 函数报出错误(此处也可以添加日志打印等操作)
return bar;
};
比较时间先后顺序可以使用字符串
js
var a = "2014-08-08";
var b = "2014-09-09";
console.log(a > b, a < b); // false true
console.log("21:00" < "09:10"); // false
console.log("21:00" < "9:10"); // true 时间形式注意补0
各种进制
8 进制: 0o 16 进制: 0x 2 进制: 0b
js
29; // 10进制
035; // 8进制29 原来的方式
0o35; // 8进制29 ES6的方式
0x1d; // 16进制29
0b11101; // 2进制29
数组的对象解构
var {1: aaa} = [8,9,10];
aaa; // 9
使用解构删除对象某个属性
let {_internal, tooBig, ...cleanObject} = {el1: '1', _internal:"secret", tooBig:{}, el2: '2', el3: '3'};
console.log(cleanObject); // {el1: '1', el2: '2', el3: '3'}
解构嵌套对象属性
js
var oo = { a: { b: { c: 1 } } };
var ff = ({ a }) => {
console.log(a);
};
ff(oo); // {b: {c: 1}}
var ff = ({ a: { b } }) => {
console.log(b);
};
ff(oo); // {c: 1}
var ff = ({
a: {
b: { c }
}
}) => {
console.log(c);
};
ff(oo); // 1
相当于:
var oo = {a: {b: {c: 1}}};
var {a} = oo; // {b: {c: 1}}
var {a: {b}} = oo; // {c: 1}
var {a: {b: {c}}} = oo; // 1