JS高阶编程

83 阅读2分钟

单例设计模式

都写在全局下,会存在全局变量污染的问题 基于闭包的方式解决全局污染的问题 [无法直接调用其他模块下的方法]

  • window.xxxx = xxx; 暴露的API不易过多
  • 基于对象分组的特点: 把当前需要供别人调用的API/信息放置到一个堆内存中,让utils指向这个堆,后期基于utils就可以访问到堆中的API

高级单例设计模式 [基于闭包管理的单例设计模式]

  • 单独的实例:基于单独的实例,来管理自己模块下的内容,保证不冲突 [实现的是分组]
  • namespace: 命名空间

把描述相同的事物的属性和方法放置在同一个命名空间下,来实现分组的特点,减少全局变量污染 => 单例设计模式 而基于闭包的方式,可以实现模块下部分方法的私有化,也可以基于单例实现API之间的公用 -> 最早期的模块化编程思想

  • AMD(require.js)
  • CMD(sea.js)
  • CommonJS(Node.js)
  • ES6Module
  • ...
let namespace1 = {};  //Object的一个实例
let namespace2 = {};  //Object的一个实例
let utils = (function () {
    const debounce = function debounce() {},
    const toType = function toType() {};
    // ...
    return {
        // ES6 debounce:debounce 
        debounce,
        toType
    };
})();

// 搜索区域
let searchModule = (function () {
    let value = null;
    const submit = function submit() {};
    const func = function func() {
        // ...
    }
    utils.debounce(func);
    
    return {
        submit
    }
})();

// 天气区域
let weatherModule = (function () {
    let city = '北京';
    const queryData = function queryData(callback) {
        let data = null;
        callback && callback(data);
    }
    const bindHTML = function bindHTML() {};
    const changeCity = function changeCity() {};
    
    return {
        init() {
            // init中管控当前模块下各个业务功能的执行顺序 [大脑] -> 命名设计模式
            queryData(function () {
                bindHTML();
                changeCity();
            });
        }
    };
})();
weatherModule.init();

惰性函数

/* function getCss(element, attr) {
    // 处理兼容
    if (window.getComputedStyle) {
        return window.getComputedStyle(element)[attr];
    }
    return element.currentStyle[attr];
} */
/* let utils = (function () {
    let compatible = window.getComputenStyle ? true : false;
    
    let getCss = function getCss() {
        if (compatible) {
             return window.getComputedStyle(element)[attr];
        }
        return element.currentStyle[attr];
    }
    
    return {
        getCss
    }
})(); */

// 需求:一个超级复杂的业务函数,而且会被执行N次,后续执行,依然想使用第一次执行处理好的逻辑,这样我们不期望每一次执行,逻辑都重新判断一下,此时基于惰性思想[函数重构可以实现性能的优化]
function getCss() {
    if (window.getComputedStyle) {
        getCss = function (element, attr) {
            return window.getComputedStyle(element)[attr];
        }
    } else {
        getCss = function (element, attr) {
            return element.currentStyle[attr];
        }
    }
    // 第一次把重写后的函数执行,获取对应的样式
    return getCss(element, attr);
}

let body = document.body;
console.log(getCss(body, 'width'));
console.log(getCss(body, 'height'));

柯里化函数

预先处理的思想[利用闭包,保存私有上下文中的一些信息,供其下级上下文中调取使用,也就是我们把一些信息先预先保存下来,后期让其下级上下文使用] => 大函数执行返回小函数

const fn = (...params) => {
    // 闭包: params -> [1,2]
    return (...args) => {
        return params.concat(args).reduce((total, item) => {
            return total + item;
        });
    }
}
fn(1,2)(3);