跟着月影大佬学JavaScript| 青训营笔记

74 阅读3分钟

20140124114736347.jpg.source.jpg 这是我参与「第五届青训营 」笔记创作活动的第3天

对于前端来说,js 可以说是非常常见的脚本语言之一了。前端工程师写的最多的代码,可能就是 js 代码了。写好 js 代码,必须要遵循到几大原则:各司其职、组件封装和过程抽象

什么才是好的JS代码?

对于好的 js 代码来说,应该要遵循的是以下三个原则。分别是:

  • 各司其职:就是让HTML、CSS和JavaScript分离开来。

  • 组件封装:好的UI组件具备正确性、扩展性、复用性。

    重构 插件化,解耦

    1. 将控制元素抽成插件
    2. 插件与组件之间通过注入依赖的方式建立联系
    3. 解耦,html模板化,更易于理解
    4. 抽象,将通用的组件模板抽象出来
  • 过程抽象:应用函数式编程思想

  • 组件封装

1.行为JS——行为API

API设计应保证原子操作、职责单一、满足灵活性

2.行为JS——控制流

使用自定义事件来进行解耦

3.重构:组件框架

解耦:解耦是将控制元素抽取成插件,插件与组件之间通过依赖注入方式建立联系。解耦将HTML模板化,更易于扩展

  • 插件化
  • 模板化
  • 抽象化(组件框架)

过程抽象

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

如何让一个事件只触发一次?

当事件触发,对应方法执行后,我们就将该方法指向设为null,这样下次再次触发该事件调用的只是null,也就不会再次执行对应方法。在一个项目中,可能不止有一个事件只需执行一次,我们就可以将设置方法只执行一次的功能部分抽离出来,设为单独的函数:

function once(fn){
    return function(...args){
        if(fn){
            const ret = fn.apply(this, args);
            fn = null;
            return ret;
        }
    }
}
复制代码

这样将功能抽离,就叫做过程抽象

而这样传入值为函数,返回值也为函数的函数,就称作高阶函数。

我们为什么需要高阶函数呢?

先来看两个概念:

  • 纯函数:返回值只由传入值确定,与外界交换数据只有这一个通道
  • 非纯函数:返回值不止或不由由传入值确定,而是通过隐式的方式与外界进行数据交换

纯函数由于其特性,更加方便移植、维护且可读性强,而非纯函数的不确定性增加了维护困难,所以我们更加推荐在开发时尽可能使用纯函数,我们使用高阶函数的其中一个目的也是将非纯函数封装拓展成纯函数

高阶函数

HOF

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

常用的高阶函数

  • once
function once(fn){
    //outer space closure
    return function(...args){
        //inner scope
        if(fn){
            const ret = fn.apply(this,args);
            fn = null;
            return ret;
        }
    }
}
复制代码
  • throttle(节流)
function throttle(fn,time = 500){
    let timer;
    return function(...args){
        if(timer == null){
            fn.apply(this,args);
            timer = setTimeout(()=> {
                timer =null
            },time)
        }
    }
}
复制代码
  • Debounced(防抖)
function debounce(fn,dur){
    dur = dur || 100;
    var timer;
    return function(){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.aply(this,arguments);
        },dur)
    }
}

复制代码

编程范式

  • Toggle - 命令式
    switch.onclick = funtion(evt){
         if(evt.target.className === "on"){
             evt.target.className = "off";
         }
         else{
             evt.target.className = "on";
         }
    }
复制代码
  • Toggle - 声明式(具有更强的可扩展性)
function toggle(...actions){
   return function(args...){
       let action = actions.shift();
       actions.push(action);
       return action.apply(this,args);
   }
}

switch.onclick = toggle(
evt.target.className = "off",
evt.target.className = "on"
)
复制代码

总结

这节课月影大佬讲的非常好,介绍了组件的封装以及代码的优化,对我们在学习javascript有着很大的帮助。经过这节课的学习我也对引入过程抽象,对代码进行优化和完善,对代码的可读性提供了很大的帮助。