深入理解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 实现的自定义对话框
Mar 24 Javascript
解析Javascript中难以理解的11个问题
Dec 09 Javascript
jQuery简单实现日历的方法
May 04 Javascript
ajax 提交数据到后台jsp页面及页面跳转问题
Jan 19 Javascript
利用Node.js对文件进行重命名
Mar 12 Javascript
angular.JS实现网页禁用调试、复制和剪切
Mar 31 Javascript
ES6中箭头函数的定义与调用方式详解
Jun 02 Javascript
Angular2 父子组件通信方式的示例
Jan 29 Javascript
jQuery添加新内容的四个常用方法分析【append,prepend,after,before】
Mar 19 jQuery
javascript实现留言板功能
Feb 08 Javascript
vue缓存之keep-alive的理解和应用详解
Nov 02 Javascript
原生JS实现分页
Apr 19 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基础教程(php入门基础教程)一些code代码
2013/01/06 PHP
在windows服务器开启php的gd库phpinfo中未发现
2013/01/13 PHP
PHP中捕获超时事件的方法实例
2015/02/12 PHP
php打包压缩文件之ZipArchive方法用法分析
2016/04/30 PHP
PHP查询附近的人及其距离的实现方法
2016/05/11 PHP
php四种定界符详解
2017/02/16 PHP
Laravel使用PHPQRCODE实现生成带有LOGO的二维码图片功能示例
2017/07/07 PHP
PHP实现搜索时记住状态的方法示例
2018/05/11 PHP
php文件上传原理与实现方法详解
2019/12/20 PHP
用一段js程序来实现动画功能
2007/03/06 Javascript
6款新颖的jQuery和CSS3进度条插件推荐
2013/03/05 Javascript
jquery div拖动效果示例代码
2013/12/08 Javascript
JavaScript中输出标签的方法
2014/08/27 Javascript
js生成的验证码的实现与技术分析
2014/09/17 Javascript
jquery图片切换插件
2015/03/16 Javascript
jQuery拖动布局其结果保存到数据库
2015/10/09 Javascript
jQuery EasyUI API 中文帮助文档和扩展实例
2016/08/01 Javascript
ionic实现可滑动的tab选项卡切换效果
2020/04/15 Javascript
JS实现双击内容变为可编辑状态
2017/03/03 Javascript
JS中正则表达式要注意lastIndex属性
2017/08/08 Javascript
vue多级复杂列表展开/折叠及全选/分组全选实现
2018/11/05 Javascript
Python转码问题的解决方法
2008/10/07 Python
分享给Python新手们的几道简单练习题
2017/09/21 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
2017/11/21 Python
Python随机生成身份证号码及校验功能
2018/12/04 Python
python已协程方式处理任务实现过程
2019/12/27 Python
Django接收照片储存文件的实例代码
2020/03/07 Python
解决Jupyter Notebook使用parser.parse_args出现错误问题
2020/04/20 Python
css3强大的动画效果animate使用说明及浏览器兼容介绍
2013/01/09 HTML / CSS
微软中国官方旗舰店:销售Surface、Xbox One、笔记本电脑、Office
2018/07/23 全球购物
教师产假请假条
2014/04/10 职场文书
好习惯伴我成长演讲稿
2014/05/21 职场文书
干部作风整顿自我剖析材料和整改措施
2014/09/18 职场文书
“四风”问题整改措施和努力方向
2014/09/20 职场文书
2014大学生批评与自我批评思想汇报
2014/09/21 职场文书
六一儿童节致辞
2015/07/31 职场文书