总结下 JavaScript 中的一些小技巧

这篇文章主要记录一下平时自己实践得到的, 博客中学习的以及在一些项目源码中看到的 javascript 技巧。有些东西可以说是奇淫技巧,有些可能是 ES6+ 中一些比较具有实用性的新语法。

&& 和 || 的妙用

有时候我们需要在某个函数或变量为 true 时执行另外一个函数。例如:

const task1 = () => {
    console.log('执行 task1');
    return Math.random() >= 0.5;
}

const task2 = () => console.log('task1 执行成功后执行 task2');
if (task1()) task2();
复制代码

上面的 if 语句可以使用 && 直接简写为:

task1() && task2();
复制代码

如果还要在 task1 失败(也就是task1返回false)后执行 task3, 可以使用:

const task3 = () => console.log('task1 执行失败后执行 task3');
task1() && task2() || task3();
复制代码

本质上还是利用了 &&|| 的短路特性。

下面展示一个我最近使用 react hooks 开发的项目的的一个代码片段:

const ProfileItem = (props) => {
    const { name, value, render } = props;

    return (
        <div className="profile-item">
            <span className="item-name">{name}</span>
            <form action="">
                {/* 根据是否有 render 这个 props 来返回不同的内容 */}
                {render && render(props) || <SimpleProfileItemContent value={value}/>}
            </form>
        </div>
    )
}
复制代码

函数默认值

ES5 版本

使用短路或操作符来设置函数默认值的方式其实很常见。但是有一些坑,下面展示的代码中当默认值参数为一个数字时,传参为 0 还是会使用默认值,必须对 y 为 0 的时候单独进行判断。

const pow = (x, y) => {
    y = y || 2;
    
    let result = 1;
    for (let i =  0, max = y; i < max; i++) {
        result *= x;
    }

    return result;
}

console.log(pow(2)); // => 4
console.log(pow(2, 3)); // => 8

// 当 y 传值为 0 时, y 取值 2
console.log(pow(2, 0)); // => 4
复制代码

ES6 版本

ES6 在语法层面提供的默认值语法就靠谱的多了

const pow = (x, y=2) => {
    let result = 1;
    for (let i =  0, max = y; i < max; i++) {
        result *= x;
    }

    return result;
}

console.log(pow(2)); // => 4
console.log(pow(2, 3)) // => 8
console.log(pow(2, 0)); // => 1
复制代码

类数组转数组

类数组指的是像 argumentsjquery 对象一样可以使用下标访问还有 length 属性的和数组很像但并不是数组的一类对象。

类数组没有 slice, map 等集合函数,这也是为什么我们有时候需要将类数组转换成数组的原因。

function func() {
    for (let i = 0, max = arguments.length; i < max; i++) {
        console.log(arguments[i]);
    }

    console.log(Array.isArray(arguments)); // => false
    // 类数组没有 slice, forEach, map 等集合函数
    console.log(arguments.slice === undefined); // => true
}

func('Google', 'facebook', 'Microsoft'); 
// => 
// Google
// facebook
// Microsoft
复制代码

ES5 中的转换方法

将 Array 原型中的 slice 方法绑定到 arguments 对象上调用,并且不传参数目的为了让其返回所有的元素。

function func() {
    const array = Array.prototype.slice.call(arguments);
    console.log(array.slice(0, 1));
}

func('Google', 'facebook', 'Microsoft'); // => [ 'Google' ]
复制代码

ES6 中的转换方法

ES6 将类数组转换成数组的方法多一些。

使用扩展运算符

function func() {
    console.log([...arguments])
}

func('Google', 'facebook', 'Microsoft'); // [ 'Google', 'facebook', 'Microsoft' ]
复制代码

使用 Array.from

function func() {
    console.log(Array.from(arguments))
}

func('Google', 'facebook', 'Microsoft'); // [ 'Google', 'facebook', 'Microsoft' ]
复制代码

构造一个连续整数的数组

这里就直接给出我觉得最好的方法了

// 输出 2 开始连续的8个整数
const array = Array.from({ length: 8}).map((ele, index) => index + 2);
console.log(array); // => [ 2, 3, 4, 5, 6, 7, 8, 9 ] 
复制代码

函数参数使用结构赋值

函数参数比较多的时候我们往往会让参数直接接受一个配置对象。但是使用对象参数我们无法设置默认值,在函数体中使用对象参数时还需要使用通过对象参数来访问,当访问次数比较多或者嵌套比较深就会觉得不方便。在函数参数中使用结构赋值就解决了上面的问题。

// 必须给对象参数设置默认值, 不然传参数时因为没有解构对象会报错
const getUsers = ({
    offset=0,
    limit=1,
    orderBy="salary"
}={}) => {
    // 根据条件查询数据库返回用户数据
    console.log({ offset, limit, orderBy });
}

getUsers({ offset: 10, limit: 20,orderBy: 'age' }); // => { offset: 10, limit: 20, orderBy: 'age' }
getUsers();// => { offset: 0, limit: 1, orderBy: 'salary' }
复制代码

使用 !! 将其它类型转换成 bool 型

console.log(!!{}); // true
console.log(!!0); // false
console.log(!![]); // true
console.log(!!undefined); // false

const httpGet = (url, retry) => {
    if (!!retry) {
        // 超时重发
    }
}
复制代码

JSON.stringify

深度克隆

使用先序列化再反序列化这种方式来深度克隆对象在一般情况下很方便,缺点就是无法克隆函数以及继承的属性。

如果还要克隆函数属性,推荐使用 lodash 的 cloneDeep。

const me = {
    name: 'lyreal666',
    age: 23,
    speak() {
        console.log(`Hello, I'm ly!`);
    }
}

const clonedMe = JSON.parse(JSON.stringify(me));
console.log(clonedMe); // => { name: 'lyreal666', age: 23 }
console.log(clonedMe.speak === undefined); // => true
复制代码

使用第二个和第三参数

JSON.stringify 的第二个参数是用来对属性设置进行处理的,第三个参数则是指定输出的 json 字符串的缩进长度,可以传数字也可以传字符串。

const me = {
    name: 'lyreal666',
    age: 23,
    speak() {
        console.log(`Hello, I'm ly!`);
    }
}

const jsonStr = JSON.stringify(me, (key, value) => key === 'name' ? '老余' : value, 2);

console.log(jsonStr);
/* =>
{
  "name": "老余",
  "age": 23
}
*/
复制代码

优雅的遍历对像

使用解构赋值和 Object.entries。

const me = {
    name: 'lyreal666',
    age: 23,
    speak() {
        console.log(`Hello, I'm ly!`);
    }
}

for (const [key, value] of Object.entries(me)) {
    console.log(`${key}: ${value}`);
}

/* =>
name: lyreal666
age: 23
speak: speak() {
        console.log(`Hello, I'm ly!`);
    }
*/
复制代码

清空数组的最快方法

const array = [1, 2, 3, 4];
array.length = 0;
console.log(array); // => []
复制代码

判断一个整数是否是 -1

// ~ 操作符的运算规律可以简单记作将加一的结果取反
console.log(~1); // => -2
console.log(~0); // => -1
console.log(~(-3)); // => 2
console.log(~(-1)); // => 0

const number = -2;

// 判断一个数是否为 -1
if (!~number) {
    // 当 number 是 -1 的操作...
}
复制代码

立即执行函数

立即执行函数可以让我们的代码中的变量不污染外部变量,常见的使用方式是像下面这样的。

// 使用括号将函数括起来调用
(function(window, $) {
    // 内部代码
}) (window, jQuery)
复制代码

更优雅的方式是下面这种,事实上很多其它的算术运算符比如 +, -, *, ~ 等也是可以的,

! function(window, $) {
    // 内部代码
} (window, jQuery)
复制代码

使用 set 来对数组去重复

console.log([...new Set([1, 3, 1, 2, 2, 1])]); // => [ 1, 3, 2 ]
复制代码

使用 reduce 连乘或连加

const array = [ 1, 2, 3, 4];
// 连加
console.log(array.reduce((p, c) => p + c)); // => 10
// 连乘
console.log(array.reduce((p, c) => p * c)); // => 24
复制代码

更多技巧待我想起来了再补充...


作者:lyreal666
链接:https://juejin.im/post/5ca4cf5651882543e31e2fab
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/89020787