首页 > 代码库 > Javascriptg高级函数
Javascriptg高级函数
Javascript高级函数
- 惰性载入函数
- 函数柯里化
- 级联函数
这并不全面,只是几个主要的。
惰性载入函数
惰性载入表示函数执行的分支只会在函数第一次掉用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。
写一个函数用来创建XmlHttpRequest对象,浏览器兼容性原因,写出的代码通过大量if判断或者try,catch语句将函数引导到正确代码处。
代码示例:
function createXHR(){ var xhr = null; try { // Firefox, Opera 8.0+, Safari,IE7+ xhr = new XMLHttpRequest(); } catch (e) { // Internet Explorer try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { xhr = null; } } } return xhr; }
每次调用这个函数的时候,都要先进行浏览器能力检查,首先检查浏览器是否支持内置的XMLHyypRequest对象,如果不支持然后检查各版本基于ActiveX的XMLHttpRequest,每次调用该函数都是这样,其实当第一次执行完后,如果浏览器支持某个特定XMLHttpRequest对象,那么下次执行的时候这种支持性并不会改变,没必要再进行一边检测,即使只有一个if语句,执行也肯定比没有要慢,如果我们可以让if语句不必每次执行,那么就可以在频繁调用的情况下提高执行速度。并且如果在多次createXHR后没有处理好,还会非常容易造成内存泄漏。解决方案就是惰性载入。在已经判断出当前浏览器是什么的时候,就让createXHR == XHR;
function createXHR(){ var xhr=null;
if(typeof XMLHttpRequest !=‘undefined‘){ xhr = new XMLHttpRequest(); createXHR=function(){ return new XMLHttpRequest(); } }else{ try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); createXHR=function(){ return new ActiveXObject("Msxml2.XMLHTTP"); } } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); createXHR=function(){ return new ActiveXObject("Microsoft.XMLHTTP"); } } catch (e) { createXHR=function(){ return null; } } } } return xhr; }
在这个惰性载入的createXHR中第一次执行的时候每个分支都会为createXHR重新赋值,覆盖原函数,返回xhr对象,而第二次执行的时候就会直接调用重写后的函数,这样就不必执行每个分支重新做检测了。
函数柯里化
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
说起函数柯里化,我理解起来确实费了很大一波力,首先对于代码中的很多部分都不理解,比如slice、call()、apply()【日后会写这三个】。理解了这些之后自然能够看懂柯里化的通用实现:
代码示例:
function currying(fn) { var args = Array.prototype.slice.call(arguments, 1); return function () { var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); console.log (finalArgs); return fn.apply(this,finalArgs); }; }
- 提高适用性
代码示例:
function square(i) { return i * i; } function dubble(i) { return i *= 2; } function map(handeler, list) { return list.map(handeler); } // 数组的每一项平方 map(square, [1, 2, 3, 4, 5]); map(square, [6, 7, 8, 9, 10]); map(square, [10, 20, 30, 40, 50]); // ...... // 数组的每一项加倍 map(dubble, [1, 2, 3, 4, 5]); map(dubble, [6, 7, 8, 9, 10]); map(dubble, [10, 20, 30, 40, 50]);
例子中,创建了一个
map
通用函数,用于适应不同的应用场景。。同时,例子中重复传入了相同的处理函数:square和dubble。应用中这种需要处理的东西会更多。通用性的增强必然带来适用性的减弱。但是,我们依然可以在中间找到一种平衡。
看下面,我们利用柯里化改造一下:
代码示例:
function square(i) { return i * i; } function dubble(i) { return i *= 2; } function map(handeler, list) { return list.map(handeler); } var mapSQ = currying(map, square); mapSQ([1, 2, 3, 4, 5]); mapSQ([6, 7, 8, 9, 10]); mapSQ([10, 20, 30, 40, 50]); // ...... var mapDB = currying(map, dubble); mapDB([1, 2, 3, 4, 5]); mapDB([6, 7, 8, 9, 10]); mapDB([10, 20, 30, 40, 50]); // ......
柯里化降低通用性,提高适用性。
- 延迟执行
不断的柯里化,累计传入的参数,最后执行。
代码示例:
var add = function() { var _this = this, _args = arguments return function() { if (!arguments.length) { var sum = 0; for (var i = 0,c; c = _args[i++];) sum += c; return sum; } else { Array.prototype.push.apply(_args, arguments)
return arguments.callee; } } } add(1)(2)(3)(4)();//10柯里化:
var curry = function(fn) { var _args = [] return function cb() { if (arguments.length == 0) { return fn.apply(this, _args) } Array.prototype.push.apply(_args, arguments); return cb; } }
- 固定易变因素
柯里化特性决定了它可以提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。
Function.prototype.bind = function(context) { var _this = this, _args = Array.prototype.slice.call(arguments, 1); return function() { return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments))) } }
但其实我还是没有那么透彻的理解函数柯里化,应该等到其他的知识掌握的更加熟练,理解起来也才会更加容易吧
级联函数
级联函数也叫链式函数,方法链一般适合对一个对象进行连续操作(集中在一句代码),一定程度上把相关的属性都连到一起,减少代码量,缺点是它占用了函数的返回值。
function myclassA(){ this.name=""; this.age=""; this.sex=""; } myclassA.prototype={ setname:function(){ this.name="katherine"; return this; }, setage:function(){ this.age="22"; return this; }, setsex:function(){ this.sex=‘girl‘; return this; } } var me =new myclassA(); console.log(me.setname().setage().setsex()); // myclassA {name: "katherine", age: "22", sex: "girl"}
这一篇整整弄了两天才弄完,但是还是有些搞不懂函数柯里化,我想只能在日后的开发中,慢慢接触项目来解锁理解了【摊手】
Javascriptg高级函数