本系列教程不会讲得特别深,通过案例,就带个入门,面试的时候,被问到能答出个所以来,在实际运用中,能把复杂的问题简单化就够了。
概念
其实在javascript里函数可以动态定义的,如果创建了一个新函数并且将其分配给保存了另外函数的同一个变量,那么新函数覆盖旧函数。
var Obj = function () { alert('乘风gg!'); Obj = function () { alert('Double 乘风gg!') }; } Obj();//'乘风gg!' Obj();//'Double 乘风gg!'复制代码
这种自定义函数的作用在于,初始化,对,你没看错,就是初始化,一般用于初始化程序并且只仅需执行一次的时候,这种方式就非常有用了,这样可以避免频繁的逻辑判断和避免重复的工作,提升应用程序的性能。
这种自定义函数其实也叫惰性函数的思想重写原来的函数是有缺陷的。一不小心就踩坑
- 当它重定义自身时已经添加到原始函数的任何属性丢会丢失。
- 如果该函数使用了不同的名称,比如分配给不同的变量或者以对象的方法来使用,那么重定义部分将永远不会发生,并且将会执行原始函数体。
练习
结合我画的丑图,下面我们来踩踩这两个坑。
继续上面的代码。Obj.property = 'property'; //赋值给另一个不同名称的变量 var modify = Obj; //作为一个方法使用 var _obj = { fn: Obj } //调用赋值给modify的情况 modify();//'乘风gg!' modify();//'乘风gg!' console.log(modify.property);//'property' //作为一个方法来调用 _obj.fn()//'乘风gg!' _obj.fn()//'乘风gg!' console.log(_obj.fn.property);//'property' //直接调用 Obj();//'Double 乘风gg!' Obj();//'Double 乘风gg!' console.log(Obj.property);//'undefined'复制代码
正如我们预期一样,每次调用modify,都是输出'乘风gg',并且还生产了一个新的函数,地址是777777,并且被Obj引用了,所以,函数modify是保持着第一次定义的旧函数,Obj是新函数,所以最后输出'undefined'。
作用:
以前我们使用ajax处理浏览器兼容的时候,不知道你们是不是这样子写的
function createXHR() { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest; } else { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Msxml3.XMLHTTP"); } catch (e) { } } } } return xhr; } var xhr = createXHR(); var xhr2 = createXHR();复制代码
由于页面肯定不止一次向服务器发送 ajax请求,那么浏览器多次执行这段createXHR的函数的时候,频繁的执行这段代码去判断浏览器的兼容性, 浪费了性能,其实只有第一次使用ajax的时候判断浏览器的兼容,然后重新定义这个ajax函数,不就好了嘛?我们来实现一下
function createXHR() { var xhr = null, flag = false, ary = [ function () { return new XMLHttpRequest; }, function () { return new ActiveXObject("Microsoft.XMLHTTP"); }, function () { return new ActiveXObject("Msxml2.XMLHTTP"); }, function () { return new ActiveXObject("Msxml3.XMLHTTP"); } ]; //循环遍历这个数组,看看数组内的哪一个元素兼容浏览器,如果兼容,就赋值给给xhr,并且返回出去 for (var i = 0, len = ary.length; i < len; i++) { var curFn = ary[i]; try { xhr = curFn(); createXHR = curFn;//重新定义createXHR ,第二次调用ajax请求,则直接使用这个方法 flag = true; break; } catch (e) { //说明浏览器不兼容,继续循环 } } if (!flag) { throw new Error("你的浏览器不支持 ,请升级浏览器"); } return xhr;}复制代码
其实还有一些方法也能达到惰性函数的思想,是利用单例模式(下一章会讲到).
总结
- 惰性函数的实现原理就是重新定义函数。
- 惰性思想的精髓:能一次搞定的事,我绝不做第二次
最后欢迎大家指正,批评,督促。
github源码地址:参照案例书籍javascript模式点赞是对我的最大支持和鼓励