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

 更新时间:2015年03月04日 11:05:57   投稿:junjie  
这篇文章主要介绍了深入理解JavaScript系列(50):Function模式(下篇),本篇我们介绍的一些模式称为初始化模式和性能模式,主要是用在初始化以及提高性能方面,一些模式之前已经提到过,这里只是做一下总结,需要的朋友可以参考下

介绍

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

立即执行的函数

在本系列第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的闭包详解

    Javascript的闭包详解

    这篇文章主要介绍了Javascript的闭包详解,需要的朋友可以参考下
    2014-12-12
  • Js逆向教程作用域和自执行函数介绍

    Js逆向教程作用域和自执行函数介绍

    这篇文章主要介绍了Js逆向教程作用域和自执行函数介绍,本文章内容详细,具有很好的参考价值,希望对大家有所帮助,需要的朋友可以参考下
    2023-01-01
  • 对JavaScript客户端应用编程的一些建议

    对JavaScript客户端应用编程的一些建议

    这篇文章主要介绍了对JavaScript客户端应用编程的一些建议,主要针对MVC框架框架的一些相关使用问题,需要的朋友可以参考下
    2015-06-06
  • JavaScript初级教程(第一课)

    JavaScript初级教程(第一课)

    JavaScript初级教程(第一课)...
    2007-04-04
  • THREE.JS入门教程(5)你应当知道的十件事

    THREE.JS入门教程(5)你应当知道的十件事

    Three.js是一个伟大的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端实现真正意义的3D,本文会让你了解一下使用THREE.JS处理3D/避免SetInterval/使用倒序循环等等,感兴趣的朋友可以了解下哦
    2013-01-01
  • JavaScript学习笔记整理_关于表达式和语句

    JavaScript学习笔记整理_关于表达式和语句

    下面小编就为大家带来一篇JavaScript学习笔记整理_关于表达式和语句。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • JavaScript学习笔记之Cookie对象

    JavaScript学习笔记之Cookie对象

    本文主要简单介绍了javascript中cookie对象的概念,以及cookie的读取,写入,删除操作的方法,并附上示例,非常不错,这里推荐给小伙伴们。
    2015-01-01
  • 浅析JavaScript异步代码优化

    浅析JavaScript异步代码优化

    这篇文章主要介绍了JavaScript异步代码优化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • JS Attribute属性操作详解

    JS Attribute属性操作详解

    下面小编就为大家带来一篇JS Attribute属性操作详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • javascript学习笔记(十二) RegExp类型介绍

    javascript学习笔记(十二) RegExp类型介绍

    javascript学习笔记之RegExp类型介绍,学习js的朋友可以参考下
    2012-06-06

最新评论