上一回聊到JS的Object类型,简单模拟了一下Java的Map,介一讲,偶们来聊一下函数好唔好,介可系JS世界的一等公民哟。从函数开始,咱们就将逐步过渡到设计模式,来吧,帅狐带你装逼带你飞:javascript
(1) 函数声明:php
function o(a,b){ return a+b; }
(2) 函数表达式:css
var o = function(a,b){ return a+b; };
(3) 构造函数式:html
var o = new Function("a","b","return a+b");
这里简单的过一下函数定义,其余函数相关的基础知识仍是那句:请参阅书籍或其余资料。java
这仨均可以改变函数内部做用域的指向,bind()是ES5的新玩意儿,IE9如下不支持。call()和apply()一起说,这俩基友仅仅是传参不同而已,apply传递的是数组:node
function add(arg1,arg2) { return arg1+arg2; }; function subtraction(arg1,arg2) { return arg1-arg2; }; function optCall(arg1,arg2){ return add.call(this,arg1,arg2); }; function optApply(arg1,arg2){ return subtraction.apply(this,[arg1,arg2]); }; alert(optCall(1,2)); // 3 alert(optApply(2,1)); // 1
再来讲说bind(),在高程3(JavaScript高级程序设计第三版)书上的说法是:bind()经常和回调函数与事件处理程序一块儿使用以便在将函数做为变量传递的同时保留代码执行环境。后面的设计模式讲解中咱们会有事件的讲解,这里咱们用书上的例子来模拟bind()的实现:mysql
function bind(fn,context){ // 这里是一个闭包 return function(){ // 这里调用传递的函数,并将参数传入 return fn.apply(context,arguments); }; }
这里光看例子可能有点抽象,不要紧,后面讲设计模式,聊到观察者模式的时候还会聊到事件。面试
闭包:有权访问另外一个函数做用域中变量的函数。这是书上的解释,有点懵吧,说白了,就是方法里面的方法就叫闭包。
柯里化:把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数并且返回结果的新函数的技术。sql
之因此把这俩放在一块儿来聊,是由于这俩都很差理解,有点绕,并且柯里化依赖于闭包来实现,来吧,直接看书上的例子:设计模式
var c = console; function curry(fn){ // 这个地方是获取Array原型的slice方法,之因此这么用,是由于数组未被实例化以前,没法得到原型上的方法,可能有点绕,先无论原型后面会讲 var _slice = Array.prototype.slice; // 这里获取的是传入的第二个参数,也就是5 var args = _slice.call(arguments,1); c.log(args); // [5] // 这里是一个闭包,这个函数的做用是组合外部传参和内部传参 return function(){ // 在这里传入的arguments是[15,10] var innerArgs = _slice.call(arguments); c.log(innerArgs); // [15,10] var finalArgs = args.concat(innerArgs); // 内外部数组合并 c.log(finalArgs); // [5,15,10] // 这里写null或是其余均可以,由于这里只是执行传入的方法,也就add()方法 return fn.apply(null,finalArgs); }; } function add(a,b,c){ return a+b+c; } alert(curry(add,5)(15,10));
不少盆友说这个例子木有看懂,如今配上了注释,赶脚有木有好点。这里没有单独聊闭包,由于网上关于闭包的资料已经不少了。
顺便在啰嗦一句,有哥们儿面试问到了,fn.apply(null,finalArgs)这里若是是null的话,指向的是什么?答案是Global,而在浏览器环境下,Global就是window。
又是装逼时刻了,好咯,开始敲代码了:
这一回讲的内容比较绕脑壳,其实全部的函数都是Function类型的实例。一时理解不了也不要紧,先囫囵吞枣,后面的内容还会涉及,下面仍是进入作题环节:
听说这家公司笔试题有四道题,这里先聊两道题,另外了道题后面会聊到...
function one(){ var tags = typeof arguments[0]; // 获取传入的第一个参数类型 var arg = ""; switch(tags){ // 判断若是是undefined,说明是最里层的函数 case 'undefined': arg = 1+""; break; // 判断若是是string,说明已经执行过最里层函数了,也就是说,已经跑过case为'undefined'的状况了 case 'string': arg = 1+arguments[0]; break; }; return arg; }; function five(){ return 5+arguments[0]; }; alert(five(one(one()))); alert(five(one(one(one(one(one(one())))))));
这个例子并不是柯里化的函数,由于每一次one()的返回都是一个字符串,可是对比函数柯里化,使函数柯里化的概念更直观了。
咱们把这个five()改改,让他变为柯里化,让帅狐show给你看:
function five(){ var args = arguments[0]; // 这里就是一个闭包的体现,而后自执行,返回的依然是字符串 return (function(){ return 5+args; })(); };
怎么样,帅吧!好吧,若是不帅,继续下一题,走你:
function unique(arr) { // res是结果数组,o是一个对象,上一回已经讲过了,对象的key是不可重复的 var res = [], o = {}; // 遍历传入的数组 for (var i=0; arr[i]!=null; i++) { // 这里把数组的值做为对象的key进行判断,若是不存在则放入 if (!o[arr[i]]) { // 这步是取过滤后的每一项放入结果数组 res.push(arr[i]); // 这步把传入值做为对象key,而且赋值 o[arr[i]] = true; } } return res; // 返回结果数组, } alert(unique(["帅狐","帅狐",9,4,9,4,"帅","帅"])); // 帅狐,9,4,帅
这样就完成了数组去重,下一步,按照倒数第二个字母排序:
var arr =['javaScript','java','mongo','mysql', 'css','html','nodejs','php']; function compare(pre,cur){ var p = pre.charAt(pre.length-2); // 取倒数第二个字母 var c = cur.charAt(cur.length-2); if(p < c){ return -1; }else if(p > c){ return 1; }else{ return 0; } } alert(arr.sort(compare)); // 返回["mongo", "php", "nodejs", "html", "javaScript", "mysql", "css", "java"]
之因此单独写第二步,由于sort()排序是按照字符编码的顺序进行排序,在传入数值的时候是有陷阱的,不会对数值大小进行排序,看例子:
var arr =[1,10,2,99,3,200]; function sortNum(a,b){ return a - b } alert(arr.sort()); // 返回[1, 10, 2, 200, 3, 99] alert(arr.sort(sortNum)); // 返回[1, 2, 3, 10, 99, 200]
这一回,主要过了一下Function类型,聊了一些函数的技巧,作了两道题,难度适中。
下一回,咱主要聊一聊,类的模拟,原型,继承,包括浅聊一下工厂模式,继续装逼继续飞。
话说最近港囧和夏洛特烦恼惹火了不少老歌,对于喜欢听老歌的我真的是大爱吖,dilililidilililidada...dilililidilililidada...
注:此系飞狐原创,转载请注明出处