几道JS题目

前言

今天总结一下这几天看到的JS题目~

1:请定义这样一个函数
function repeat (func, times, wait) {

}
这个函数能返回一个新函数,比如这样用
var repeatedFun = repeat(alert, 10, 5000)
调用这个 repeatedFun (“hellworld”)
会alert十次 helloworld, 每次间隔5秒

关于第一道,之前写轮播和弹幕的时候自己遇到过,JS的多次延迟执行,需要用到setInterval和if的判断。
我的实现如下:

 function repeat (func, times, wait) {
   function repeatImpl(){
     var handle,
         _arguments = arguments,
        i = 0;
     handle = setInterval(function(){
         i = i + 1;
         //到达指定次数取消定时器
         if(i === times){
            clearInterval(handle);
          return;
         }
        func(_arguments);
     },wait);
}

 return repeatImpl;
  }
测试用例
var repeatFun = repeat(console.log, 4, 3000);

 repeatFun("hellworld");

这道题目有几点需要注意!首先,延迟器的添加和取消,函数作为参数的导入。
关于延迟器,既可以令i=0,也可以令i=times;可以用if也可以用&&来进行清除。其次,函数导入时,有几种写法:func();func(arguments);func.apply(null,arguments);
需要传入参数时可以用后面的写法。
这题有几个容易错误的地方:
1:用for循环
有很多人第一时间会想着用for循环结合setTimeout函数。这样子会发生两个问题。
第一:很多时候for循环内部若是要利用循环的i值,需要利用自执行函数加闭包。
第二:如果用了,会导致,先延迟wait秒,之后连续弹出times次数的对话框。
前者是作用域问题导致只能取到代码执行完毕后i的最终值。
后者的问题是,setTimeout是异步函数,JS是单线程无阻塞的,十次(假设)会马上执行完,然后5秒等待后一起弹出,当然还是有先后的,不过JS做十次循环的时间可以忽略不计。
这里也说明了之前无法完美读到currentTime的问题~因为JS的解析是有时间的。
2:
写一个函数stringconcat, 要求能
var result1 = stringconcat(“a”, “b”) result1 = “a+b”
var stringconcatWithPrefix = stringconcat.prefix(“hellworld”);
var result2 = stringconcatWithPrefix(“a”, “b”) result2 = “hellworld+a+b”
先来读读题,我开始读题的时候懵逼了的(因为自己太water了)
首先第一个函数的效果:把传入的字符串拼接起来。
第二个等号,把右侧的内容赋给左边,之后左边这个能够传入参数是个函数,那么stringconcat.prefix是stringconcat的方法。
OK我的实现如下:

function stringconcat(){
var result0 = []; 
result0 = Array.prototype.slice.call(arguments);
var result = result0.join('+');
return result;
 }
var result1 = stringconcat('a','b');
stringconcat.prefix = function(pre){
function prefixConcat(){
    var result0 = [pre];
    var result1 = Array.prototype.slice.call(arguments);
    var result2 = result0.concat(result1);
    var result3 = result2.join('+');
    return result3;
}
return prefixConcat;
}
var stringconcatWithPrefix = stringconcat.prefix("joke");
var result2 = stringconcatWithPrefix("a", "b");
alert(result2);

这题的考点在arguments对象,这个对象是个数组对象,它具有数组的特性,能够通过[i]来访问。但是他是一个对象不能进行数组操作,所以我们需要把它转变成为数组。那么我们可以用[].slice.call();的方法,当然用原型也是一样的~,把它变成数组后,就可以用我们的join方法,用加号把数组内的元素用字符串拼接起来。
第二个函数也是非常的简单,他返回了一个函数,这个函数可以在arguments的头前面加一个字符串。。那么我们直接把初始字符串当做函数引入进来,然后把arguments用concat割入到初始数组,再用join连接起来就好~
这题的注意点还有一个就是,返回函数的问题。平时很少很少写这类的呢囧。其次这也提醒了我一个盲点,就是关于stringconcat.prefix,跟一般的对象添加方法不一样。。这个坑下次就填上!
3:
有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e
请写一段JS程序提取URL中的各个GET参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中,如{a:’1′, b:’2′, c:”, d:’xxx’, e:undefined}。
咳咳!这个题目答案就直接给出吧~也牵扯到了数组对象。

function serilizeUrl(url) {
var result = {};
url = url.split("?")[1];
var map = url.split("&");
for(var i = 0, len = map.length; i < len; i++) {
    result[map[i].split("=")[0]] = map[i].split("=")[1];
}
return result;
}

来解释一下!返回的是一个JSON对象。
首先困难模式就是先用正则匹配?开头的字符串。。
正确姿势就如上的,用?把整个字符串打断,变成一个二元的数组,我们直接取出[1],第二项来~就是?后的一段。
之后哦我们再次打断,用&进行分割,得到一个五元数组;我们的数组对象如何就用for循环来表示!
将键值数的项一个个推入;
键是,map[i].split(‘=’)[0],把单项用=打断后的前一个,
值是后一个~
最后返回result。
TIP:数组对象能够用arryObj[ key ] 来选中 value,也可以通过这种写法来赋值。
slice,split,concat,join真的是合并和打断的小能手。。
4:
数组去重。这里找到个很简单的方法:
function removeRepeat(arr){
return arr.filter(function(elem, pos) {
return arr.indexOf(elem) == pos;//数组中,该元素首次出现的位置等于它的位置时,则过滤出来
});
}
把传入的数组用filter进行过滤,fiter的参数有item每一项,和index序号。filter需要return一个条件:
我们条件是 arr.indexOf(item) == pos;它首次出现的位置,和它的位置是相等的! indexOf返回首次出现元素的位置!

结语

关于正则的问题,下一篇来细说,模板函数什么的真是麻烦。。。本water压力好大Orz.