JS | 青训营笔记

80 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

JavaScript编码原则

写好JS的一些原则

各司其职

让HTML、CSS和JavaScript职能分离

例子:

黑白主题的切换

version1(通过JS代码来更改CSS样式)

可以达到最终的效果,但更改麻烦,且他人阅读时不易看出代码的目的,不利于合作开发

const btn = document.getElemntById('modeBtn');
btn.addEventListener('click', (e) => {
    const body = document.body;
    if (e.target.innerHTML === 'light'){
        body.style.backgroundColor = 'black';
        body.style.color = 'white';
        e.target.innerHTML = 'night';
    }else if{
        body.style.backgroundColor = 'white';
        body.style.color = 'black';
        e.target.innerHTML = 'light';
    }
});

version2(通过JS代码更改CSS元素的类名)

const btn = document.getElemntById('modeBtn');
btn.addEventListener('click', (e) => {
    const body = document.body;
    if (body.className != 'night'){
        body.className = 'night'
    }else if{
        body.className = ''
    }
});

version3(直接在CSS中用checkbox来更改样式)

#modeBtn:checked + .content {
    background-color: black;
    color: white;
    transition: all 1s;
}

组件封装

好的UI组件具备正确性、扩展性、复用性

实现组件的步骤

  1. 结构设计
  2. 展示效果
  3. 行为设计

过程抽象

  • 用来处理局部细节控制的一些方法
  • 函数式编程思想的基础应用

操作次数限制

  • 一些异步交互
  • 一次性的HTTP请求
const list = document.querySeletor('ul');
const buttons = list.querySelectorAll('button');
buttons.forEach( (button) => {
    button.addEventListener('click', (evt)=> {
        const target = evt.target;
        target.parentNode.className = 'completed';
        setTimeout( ()=> {
            list.removeChild(target.parentNode);
        }, 2000);
    });
});
once

为了能够让“只执行一次”的需求覆盖不同的事件处理,我们可以将这个需求剥离出来。这个过程称为过程抽象

function once(fn) {
    return function(...args){
        if(fn){
            const result = fn.apply(this,args);
            fn = null;
            return result;
        }
    }
}

高阶函数

  • 以函数作为参数
  • 以函数作为返回值
  • 常用于作为函数装饰器
function HOF0(fn){
    return function(...args){
        return fn.apply(this, args);
    }
}

纯函数

编程范式

命令式和声明式

命令式强调如何做

声明式强调做什么

命令式
swicher.onclick = function(){
    if(event.target.className === 'on'){
        event.target.className = 'off';
}else{
    event.target.className = 'on';
}
}
声明式

适用于更多样式的情况(可扩展性更好)

function toggle(...actions){                //接收多个actions
    return function(...args){
        let action = actions.shift();       //将第一个action取出来
        actions.push(action);               //将上一步取出来的action添加到后面,即第二个action变成第一个
        return action.apply(this, args);
    }
}
​
swicher.onclick = toggle{
    event => event.target.className = 'off',
    event => event.target.className = 'on'
};

如何写好JS

怎么看一段代码写的好不好?

首先,我们不能只因为一段代码的逻辑简单基础,或者说这个函数被写“死”了就说这个代码写的不好,而要看这段代码具体的应用场景,

比如课程中所说的Left-pad事件,代码如下。

function lefhpad (str, len, ch){
    str = String(str);
    var i = -1;
    if(!ch && ch == 0) 
        ch = ' ';
    len = len - str.length;
    while(++i < len){
        str = ch + str;
    }
    return str;
}

后来出现很多更简洁,效率更好的版本,但是原版本的代码真的就不好吗?

从实际出发的话,后面出现的很多版本确实在性能上比原版本要好,但是我们看回这段代码在应用场景的实际作用。只不过是在一个已有的字符串前面加几个字符,充其量也就十个以内,对于今天的电脑硬件来说,相信不管用前者还是后者运行效率上肯定不会有什么差距。笔者想起之前看的一本书《深入理解计算机系统》,里面就有讲到关于提升效率的问题,里面提出了一个公式(具体不太记得),大体就是说如果想提升整体效率,那么我们就应该要在占整体比重更大的部分去做优化。就算我们把一小部分的速度提升到极致,我们最后整体效率得到的提升也不会高。

总结来说,要想显著提升整个系统的效率,就必须提升整个系统中大部分的运行效率。