深入理解JavaScript系列(50):Function模式(下篇)


Posted in Javascript onMarch 04, 2015

介绍

本篇我们介绍的一些模式称为初始化模式和性能模式,主要是用在初始化以及提高性能方面,一些模式之前已经提到过,这里只是做一下总结。

立即执行的函数

在本系列第4篇的《立即调用的函数表达式》中,我们已经对类似的函数进行过详细的描述,这里我们只是再举两个简单的例子做一下总结。

// 声明完函数以后,立即执行该函数

(function () {

    console.log('watch out!');

} ());
//这种方式声明的函数,也可以立即执行

!function () {

    console.log('watch out!');

} ();
// 如下方式也都可以哦

~function () { /* code */ } ();

-function () { /* code */ } ();

+function () { /* code */ } ();

立即执行的对象初始化

该模式的意思是指在声明一个对象(而非函数)的时候,立即执行对象里的某一个方法来进行初始化工作,通常该模式可以用在一次性执行的代码上。

({

    // 这里你可以定义常量,设置其它值

    maxwidth: 600,

    maxheight: 400,
    //  当然也可以定义utility方法

    gimmeMax: function () {

        return this.maxwidth + "x" + this.maxheight;

    },
    // 初始化

    init: function () {

        console.log(this.gimmeMax());

        // 更多代码...

    }

}).init();  // 这样就开始初始化咯

分支初始化

分支初始化是指在初始化的时候,根据不同的条件(场景)初始化不同的代码,也就是所谓的条件语句赋值。之前我们在做事件处理的时候,通常使用类似下面的代码:

var utils = {

    addListener: function (el, type, fn) {

        if (typeof window.addEventListener === 'function') {

            el.addEventListener(type, fn, false);

        } else if (typeof document.attachEvent !== 'undefined') {

            el.attachEvent('on' + type, fn);

        } else {

            el['on' + type] = fn;

        }

    },

    removeListener: function (el, type, fn) {

    }

};

我们来改进一下,首先我们要定义两个接口,一个用来add事件句柄,一个用来remove事件句柄,代码如下:

var utils = {

    addListener: null,

    removeListener: null

};

实现代码如下:
if (typeof window.addEventListener === 'function') {

    utils.addListener = function (el, type, fn) {

        el.addEventListener(type, fn, false);

    };

} else if (typeof document.attachEvent !== 'undefined') { // IE

    utils.addListener = function (el, type, fn) {

        el.attachEvent('on' + type, fn);

    };

    utils.removeListener = function (el, type, fn) {

        el.detachEvent('on' + type, fn);

    };

} else { // 其它旧浏览器

    utils.addListener = function (el, type, fn) {

        el['on' + type] = fn;

    };

    utils.removeListener = function (el, type, fn) {

        el['on' + type] = null;

    };

}

用起来,是不是就很方便了?代码也优雅多了。

自声明函数

一般是在函数内部,重写同名函数代码,比如:

var scareMe = function () {

    alert("Boo!");

    scareMe = function () {

        alert("Double boo!");

    };

};

这种代码,非常容易使人迷惑,我们先来看看例子的执行结果:
// 1. 添加新属性

scareMe.property = "properly";

// 2. scareMe赋与一个新值

var prank = scareMe;

// 3. 作为一个方法调用

var spooky = {

    boo: scareMe

};

// 使用新变量名称进行调用

prank(); // "Boo!"

prank(); // "Boo!"

console.log(prank.property); // "properly"

// 使用方法进行调用

spooky.boo(); // "Boo!"

spooky.boo(); // "Boo!"

console.log(spooky.boo.property); // "properly"

通过执行结果,可以发现,将定于的函数赋值与新变量(或内部方法),代码并不执行重载的scareMe代码,而如下例子则正好相反:
// 使用自声明函数

scareMe(); // Double boo!

scareMe(); // Double boo!

console.log(scareMe.property); // undefined

大家使用这种模式时,一定要非常小心才行,否则实际结果很可能和你期望的结果不一样,当然你也可以利用这个特殊做一些特殊的操作。

内存优化

该模式主要是利用函数的属性特性来避免大量的重复计算。通常代码形式如下:

var myFunc = function (param) {

    if (!myFunc.cache[param]) {

        var result = {};

        // ... 复杂操作 ...

        myFunc.cache[param] = result;

    }

    return myFunc.cache[param];

};
// cache 存储

myFunc.cache = {};

但是上述代码有个问题,如果传入的参数是toString或者其它类似Object拥有的一些公用方法的话,就会出现问题,这时候就需要使用传说中的hasOwnProperty方法了,代码如下:
var myFunc = function (param) {

    if (!myFunc.cache.hasOwnProperty(param)) {

        var result = {};

        // ... 复杂操作 ...

        myFunc.cache[param] = result;

    }

    return myFunc.cache[param];

};
// cache 存储

myFunc.cache = {};

或者如果你传入的参数是多个的话,可以将这些参数通过JSON的stringify方法生产一个cachekey值进行存储,代码如下:
var myFunc = function () {

    var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),

        result;

    if (!myFunc.cache[cachekey]) {

        result = {};

        // ... 复杂操作 ...

        myFunc.cache[cachekey] = result;

    }

    return myFunc.cache[cachekey];

};
// cache 存储

myFunc.cache = {};

或者多个参数的话,也可以利用arguments.callee特性:
var myFunc = function (param) {

    var f = arguments.callee,

        result;

    if (!f.cache[param]) {

        result = {};

        // ... 复杂操作 ...

        f.cache[param] = result;

    }

    return f.cache[param];

};
// cache 存储

myFunc.cache = {};

总结

就不用总结了吧,大家仔细看代码就行咯

Javascript 相关文章推荐
jQuery html()等方法介绍
Nov 18 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
May 17 Javascript
使用纯javascript实现经典扫雷游戏
Apr 23 Javascript
jQuery的promise与deferred对象在异步回调中的作用
May 03 Javascript
DIV+CSS+jQ实现省市联动可扩展
Jun 22 Javascript
浅谈EasyUi ComBotree树修改 父节点选择的问题
Nov 07 Javascript
@ResponseBody 和 @RequestBody 注解的区别
Mar 08 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
Sep 19 Javascript
vue-cli项目中使用Mockjs详解
May 14 Javascript
Bootstrap fileinput 上传新文件移除时触发服务器同步删除的配置
Oct 08 Javascript
怎样在vue项目下添加ESLint的方法
May 16 Javascript
vue.js 解决v-model让select默认选中不生效的问题
Jul 28 Javascript
深入探讨javascript中的数据类型
Mar 04 #Javascript
深入理解JavaScript系列(49):Function模式(上篇)
Mar 04 #Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
Mar 04 #Javascript
jQuery中大家不太了解的几个方法
Mar 04 #Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
Mar 04 #Javascript
js计算德州扑克牌面值的方法
Mar 04 #Javascript
深入理解JavaScript系列(47):对象创建模式(上篇)
Mar 04 #Javascript
You might like
php生成缩略图填充白边(等比缩略图方案)
2013/12/25 PHP
浅析Yii2 gridview实现批量删除教程
2016/04/22 PHP
PHP简单日历实现方法
2016/07/20 PHP
通过chrome浏览器控制台(Console)进行PHP Debug的方法
2016/10/19 PHP
firefox中JS读取XML文件
2006/12/21 Javascript
精通Javascript系列之数据类型 字符串
2011/06/08 Javascript
javascript加号"+"的二义性说明
2013/03/04 Javascript
JQuery获取各种宽度、高度(format函数)实例
2013/03/04 Javascript
JS实现简单的Canvas画图实例
2013/07/04 Javascript
jQuery移动web开发中的页面初始化与加载事件
2015/12/03 Javascript
Bootstrap轮播加上css3动画,炫酷到底!
2015/12/22 Javascript
JS控件bootstrap suggest plugin使用方法详解
2017/03/25 Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
2017/09/26 Javascript
bootstrap Table的一些小操作
2017/11/01 Javascript
使用JS获取页面上的所有标签
2018/10/18 Javascript
微信小程序 swiper 组件遇到的问题及解决方法
2019/05/26 Javascript
pyqt5 使用label控件实时显示时间的实例
2019/06/14 Python
Django框架视图层URL映射与反向解析实例分析
2019/07/29 Python
pycharm编写spark程序,导入pyspark包的3中实现方法
2019/08/02 Python
详解python中*号的用法
2019/10/21 Python
Python实现i人事自动打卡的示例代码
2020/01/09 Python
利用python实现凯撒密码加解密功能
2020/03/31 Python
Python爬虫工具requests-html使用解析
2020/04/29 Python
python中urllib.request和requests的使用及区别详解
2020/05/05 Python
15款Python编辑器的优缺点,别再问我“选什么编辑器”啦
2020/10/19 Python
在weblogic中发布ejb需涉及到哪些配置文件
2012/01/17 面试题
护士的岗位职责
2013/12/04 职场文书
院领导写的就业推荐信
2014/03/09 职场文书
班主任对学生的评语
2014/04/26 职场文书
中等生评语大全
2014/05/04 职场文书
学习演讲稿范文
2014/05/10 职场文书
2015年教学管理工作总结
2015/05/20 职场文书
《孙子兵法》:欲成大事者,需读懂这些致胜策略
2019/08/23 职场文书
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
2021/05/25 Python
Pytorch 如何实现常用正则化
2021/05/27 Python
python 镜像环境搭建总结
2022/09/23 Python