如何编写优雅的代码,这是一个持续学习的过程,保持每天学习,每天进步一点点。今天中午学习巩固代码优化过程中可以用到的技术。

一、闭包

闭包是javascript中的一个重要特征,闭包就是指内部函数总是能够访问外部函数的变量和参数,即使外部函数已经返回。闭包是一把“双刃剑”,用得不恰当会带来BUG,用得恰到好处可以提升代码质量。

使用闭包可以用来保护不希望暴露给外部作用域的数据。假设每次单击按钮时将计数器变量加1,如下:

;

下面我们就来说说函数buttonCounter的实现。

可以在页面上使用全局变量的方式,如下:

let counter = 0;
function buttonCounter() {
    counter++;
}

问题是,可以直接更改变量counter,而不需要调用buttonCounter()函数,即存在副作用。

如果不用全局变量的方式,如下:

function buttonCounter() {
    let counter = 0;
    counter++;
}

现在的问题是并没有实现计数器的功能,每次计数被重置。这个时候可以考虑使用闭包,如下:

const buttonCounter = (() => {
    let counter = 0;
    return () => {
        counter = counter + 1;
        return counter;
    };
})();

上面用0初始化计数器变量,然后返回一个可以访问计数器变量的函数(函数返回计数器变量最新值)。当调用buttonCounter() 时,它将按预期累加更新计数器。

二、函数绑定

曾经遇到过这样的问题,将一个对象方法作为回调进行传递,结果传丢了,导致异常,如下:

const article = {
    title: "javascript代码优化的5个小技巧",
    printTitle() {
        console.log(`文章标题: ${this.title}`);
    },
};
setTimeout(blog.printTitle, 1000); // 文章标题: undefined

上面期望程序的输出结果为:文章标题: javascript代码优化的5个小技巧,最终并未达到预期,以至上下文丢失了。

为了解决这个问题,可以使用函数绑定的方法。

const article = {
    title: "javascript代码优化的5个小技巧",
    printTitle() {
        console.log(`文章标题: ${this.title}`);
    },
};

const printTitle = article.printTitle.bind(article);

setTimeout(printTitle, 500); // 文章标题: javascript代码优化的5个小技巧

三、递归

编程中的一些需求用传统方法解决是极其困难的。需要大量的逻辑和思考。但是,如果应用递归技术,就会简单得多。这是一种把一个大任务分解成几个同类的更小更简单的任务的技巧,无需过多思考就能理解。

当看到函数在调用自身时,就知道使用的是递归技术。

例如,需要编写一个函数,它以 xn 为参数,并返回将 x 乘以 n 的值。

传统的方式就是使用循环,如下:

const power = (x, n) => {
    let result = 1;
    for (let i = 0; i < n; i++) {
        result = result * x;
    }
    return result;
};
console.log(power(2, 9)); // 512

而用递归方法实现,代码就优雅多了,如下:

const power = (x, n) => (n === 1 ? x : x * power(x, n - 1));
console.log(power(2, 9)); // 512

上面只是递归的一个简单示例,也可以用传统方式轻松实现。但是,在编程过程中,为了简单起见,会遇到一些希望通过使用递归来解决的需求。

四、定义命名空间

随着项目的迭代,代码模块间发生命名冲突的机会就越大。避免冲突的最佳方法之一就是使用名称空间,这是一种允许用唯一名称包装部分代码的方法。

下面就是最简单的命名空间示例:

const gameActions = {
    run: () => {
        console.log("run");
    },
    jump: () => {
        console.log("jump");
    },
};

就可以像这样调用方法:gameActions.run() gameActions.jump()

今天的学习就到此,明天继续!