《编写可维护的JavaScript》(六,七,八) ---全局变量,事件处理,类型判断

93 阅读2分钟

全局变量

全局变量带来的问题:

  • 命名冲突

  • 代码脆弱性

    • 任一地方修改了全部变量,都可能使所有使用全局变量的地方出错
  • 难以测试

避免意外定义全局变量

  • var

    function fn(){
        var count = 10
            name = 'jack'
    }
    

    name将创建为全局变量,使用呢eslint等工具可以有效防范

单全局变量

创建一个唯一的全局对象,将所有的其他全局变量都挂载到该全局对象上,就像jquery等大量第三方库使用该种方式管理全局变量

命名空间

即使使用单全局变量,全局变量内部也可能产生污染,因此可以在全局对象内部以属性的方式创建单独的命名空间:

const $all = {
    命名空间1: {},
    命名空间2: {}
}

模块化

现在常用的有两种规范ESM规范和CommonJS规范,有兴趣可直接翻阅阮大的博客:Javascript模块化编程

事件处理

核心思想是逻辑分离:即事件逻辑和应用逻辑的分离.先来一个常见未分离逻辑的写法,后文中以此为基础进行讨论

function handleClick = function(event){
    ....
} 
dom.addEventListener('click',handleClick)

隔离应用逻辑

上述案例中事件处理程序包含了应用逻辑,这段应用逻辑如果将来可能会在其他地方出现(比如这里的应用逻辑是弹个弹窗),那么将不可避免的写重复代码,最好是将应用逻辑和事件处理逻辑分离:

const appLication = {
    handclick(event){
        this.showModel()
    },
    showModel(event){
        ....
    }
}
dom.addEventListener('click',(event) => {
    appLication.handclick(event)
})

这么做,将应用逻辑剥离到showModel中达到多种情况下复用的目的,

不要分发事件对象

然而上述的代码还不够完美,event对象一直在来回传递,即使在showModel中不需要使用event的全部属性,同是也导致不容易测试showModel函数,因此可以进一步将需要的值传递给showModel

const appLication = {
    handclick(event){
        // 作为事件逻辑函数,像阻止事件冒泡,阻止默认行为都可以在这里做,而不会将这些事件逻辑融合到应用逻辑中
        this.showModel(event.clientX,event.clientY)
    },
    showModel(x,y){
        ....
    }
}
dom.addEventListener('click',(event) => {
    appLication.handclick(event)
})

类型判断

判断原始值

推荐使用typeof,检测string,undefined,number,boolean,symbol是非常安全的

判断引用值

  • 数组: Array.isArray()
  • 对象: Object.prototype.toString.call() 返回[object Object],(ps: 总感觉这个最靠谱)
  • 函数: typeof
  • 自定义,日期,正则: instanceof

判断属性

推荐使用inhasOwnProperty

  • in

    • 属性自身存在或继承自原型都会返回true
  • hasOwnProperty

    • 检测自身是否包含该属性,不包括原型链中的属性