加载中...

(50)Function模式(下篇)


介绍

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

立即执行的函数

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

  1. // 声明完函数以后,立即执行该函数
  2. (function () {
  3. console.log('watch out!');
  4. } ());
  5. //这种方式声明的函数,也可以立即执行
  6. !function () {
  7. console.log('watch out!');
  8. } ();
  9. // 如下方式也都可以哦
  10. ~function () { /* code */ } ();
  11. -function () { /* code */ } ();
  12. +function () { /* code */ } ();

立即执行的对象初始化

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

  1. ({
  2. // 这里你可以定义常量,设置其它值
  3. maxwidth: 600,
  4. maxheight: 400,
  5. // 当然也可以定义utility方法
  6. gimmeMax: function () {
  7. return this.maxwidth + "x" + this.maxheight;
  8. },
  9. // 初始化
  10. init: function () {
  11. console.log(this.gimmeMax());
  12. // 更多代码...
  13. }
  14. }).init(); // 这样就开始初始化咯

分支初始化

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

  1. var utils = {
  2. addListener: function (el, type, fn) {
  3. if (typeof window.addEventListener === 'function') {
  4. el.addEventListener(type, fn, false);
  5. } else if (typeof document.attachEvent !== 'undefined') {
  6. el.attachEvent('on' + type, fn);
  7. } else {
  8. el['on' + type] = fn;
  9. }
  10. },
  11. removeListener: function (el, type, fn) {
  12. }
  13. };

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

  1. var utils = {
  2. addListener: null,
  3. removeListener: null
  4. };

实现代码如下:

  1. if (typeof window.addEventListener === 'function') {
  2. utils.addListener = function (el, type, fn) {
  3. el.addEventListener(type, fn, false);
  4. };
  5. } else if (typeof document.attachEvent !== 'undefined') { // IE
  6. utils.addListener = function (el, type, fn) {
  7. el.attachEvent('on' + type, fn);
  8. };
  9. utils.removeListener = function (el, type, fn) {
  10. el.detachEvent('on' + type, fn);
  11. };
  12. } else { // 其它旧浏览器
  13. utils.addListener = function (el, type, fn) {
  14. el['on' + type] = fn;
  15. };
  16. utils.removeListener = function (el, type, fn) {
  17. el['on' + type] = null;
  18. };
  19. }

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

自声明函数

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

  1. var scareMe = function () {
  2. alert("Boo!");
  3. scareMe = function () {
  4. alert("Double boo!");
  5. };
  6. };

这种代码,非常容易使人迷惑,我们先来看看例子的执行结果:

  1. // 1\. 添加新属性
  2. scareMe.property = "properly";
  3. // 2\. scareMe赋与一个新值
  4. var prank = scareMe;
  5. // 3\. 作为一个方法调用
  6. var spooky = {
  7. boo: scareMe
  8. };
  9. // 使用新变量名称进行调用
  10. prank(); // "Boo!"
  11. prank(); // "Boo!"
  12. console.log(prank.property); // "properly" // 使用方法进行调用
  13. spooky.boo(); // "Boo!"
  14. spooky.boo(); // "Boo!"
  15. console.log(spooky.boo.property); // "properly"

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

  1. // 使用自声明函数
  2. scareMe(); // Double boo!
  3. scareMe(); // Double boo!
  4. console.log(scareMe.property); // undefined

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

内存优化

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

  1. var myFunc = function (param) {
  2. if (!myFunc.cache[param]) {
  3. var result = {};
  4. // ... 复杂操作 ...
  5. myFunc.cache[param] = result;
  6. }
  7. return myFunc.cache[param];
  8. };
  9. // cache 存储
  10. myFunc.cache = {};

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

  1. var myFunc = function (param) {
  2. if (!myFunc.cache.hasOwnProperty(param)) {
  3. var result = {};
  4. // ... 复杂操作 ...
  5. myFunc.cache[param] = result;
  6. }
  7. return myFunc.cache[param];
  8. };
  9. // cache 存储
  10. myFunc.cache = {};

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

  1. var myFunc = function () {
  2. var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
  3. result;
  4. if (!myFunc.cache[cachekey]) {
  5. result = {};
  6. // ... 复杂操作 ...
  7. myFunc.cache[cachekey] = result;
  8. }
  9. return myFunc.cache[cachekey];
  10. };
  11. // cache 存储
  12. myFunc.cache = {};

或者多个参数的话,也可以利用arguments.callee特性:

  1. var myFunc = function (param) {
  2. var f = arguments.callee,
  3. result;
  4. if (!f.cache[param]) {
  5. result = {};
  6. // ... 复杂操作 ...
  7. f.cache[param] = result;
  8. }
  9. return f.cache[param];
  10. };
  11. // cache 存储
  12. myFunc.cache = {};

总结

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


还没有评论.