Javascript基础程序测试题

1、找出元素 item 在给定数组 arr 中的位置 
如果数组中存在 item,则返回元素在数组中的位置,否则返回 -1
function indexOf(arr, item) {
return arr.indexOf(item);
}

2、计算给定数组 arr 中所有元素的总和 
function sum(arr) {
var len = arr.length;
if(len == 0){
return 0;
} else if (len == 1){
return arr[0];
} else {
return arr[0] + sum(arr.slice(1));
}
}
常规循环:
function sum(arr) {
var s = 0;
for (var i=arr.length-1; i>=0; i--) {
s += arr[i];
}
return s;
}
函数式编程 map-reduce:
function sum(arr) {
return arr.reduce(function(prev, curr, idx, arr){
return prev + curr;
});
}
forEach遍历:
function sum(arr) {
var s = 0;
arr.forEach(function(val, idx, arr) {
s += val;
}, 0);
return s;
};
eval:
function sum(arr) {
return eval(arr.join("+"));
};

3、移除数组 arr 中的所有值与 item 相等的元素。直接修改数组 arr,结果返回
function removeWithoutCopy(arr, item) {
for(var i=0;i
if(arr[i]==item){
arr.splice(i,1);
i--;
}
}
return arr;
}

4、删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组 
function truncate(arr) {
    return arr.slice(0, -1);
 }
 
5、在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组 
//使用slice浅拷贝+push组合
var append2 = function(arr, item) {
    var newArr = arr.slice(0);  // slice(start, end)浅拷贝数组
    newArr.push(item);
    return newArr;
};
 // 使用concat将传入的数组或非数组值与原数组合并,组成一个新的数组并返回
var append3 = function(arr, item) {
    return arr.concat(item);
};


6、在数组 arr 开头添加元素 item。不要直接修改数组 arr,结果返回新的数组 
//利用concat
function prepend(arr, item) {
    return [item].concat(arr);
}
//使用push.apply
function prepend(arr, item) {
    var newArr=[item];
    [].push.apply(newArr, arr);
    return newArr;
}
//利用slice+unshift/splice
function prepend(arr, item) {
    var newArr=arr.slice(0);
    newArr.unshift(item);//newArr.splice(0,0,item);
    return newArr;
}
//使用join+split+unshift/splice组合
function prepend(arr, item) {
    var newArr=arr.join().split(',');
    newArr.unshift(item);//newArr.splice(0,0,item);
    return newArr;
}
//普通的迭代拷贝
function prepend(arr, item) {
    var newArr=[];
    for(var i=0;i
        newArr.push(arr[i]);
    }
    newArr.unshift(item);
    return newArr;
}

7、删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组 
//利用slice
function curtail(arr) {
    return arr.slice(1);
}
//利用filter
function curtail(arr) {
    return arr.filter(function(v,i) {
        return i!==0;
    });
}
//利用push.apply+shift
function curtail(arr) {
    var newArr=[];
    [].push.apply(newArr, arr);
    newArr.shift();
    return newArr;
}
//利用join+split+shift    注意!!!:数据类型会变成字符型
function curtail(arr) {
    var newArr = arr.join().split(',');
    newArr.shift();
    return newArr;
}
//利用concat+shift
function curtail(arr) {
    var newArr = arr.concat();
    newArr.shift();
    return newArr;
}
//普通的迭代拷贝
function curtail(arr) {
    var newArr=[];
    for(var i=1;i
        newArr.push(arr[i]);
    }
    return newArr;
}

8、合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组 
//利用concat
function concat(arr1, arr2) {
    return arr1.concat(arr2);
}
//利用slice+push.apply
function concat(arr1, arr2) {
    var newArr=arr1.slice(0);
    [].push.apply(newArr, arr2);
    return newArr;
}
//利用slice+push
function concat(arr1, arr2) {
    var newArr=arr1.slice(0);
    for(var i=0;i
        newArr.push(arr2[i]);
    }
    return newArr;
}
//普通的迭代拷贝
function concat(arr1, arr2) {
    var newArr=[];
    for(var i=0;i
        newArr.push(arr1[i]);
    }
    for(var j=0;j
        newArr.push(arr2[j]);
    }
    return newArr;
}

9、在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组 
//利用slice+concat
function insert(arr, item, index) {
    return arr.slice(0,index).concat(item,arr.slice(index));
}
//利用concat +splice
function insert(arr, item, index) {
    var newArr=arr.concat();
    newArr.splice(index,0,item);
    return newArr;
}
//利用slice+splice
function insert(arr, item, index) {
    var newArr=arr.slice(0);
    newArr.splice(index,0,item);
    return newArr;
}
//利用push.apply+splice
function insert(arr, item, index) {
    var newArr=[];
    [].push.apply(newArr, arr);
    newArr.splice(index,0,item);
    return newArr;
}
//普通的迭代拷贝
function insert(arr, item, index) {
    var newArr=[];
    for(var i=0;i
        newArr.push(arr[i]);
    }
    newArr.splice(index,0,item);
    return newArr;
}

10、统计数组 arr 中值等于 item 的元素出现的次数
//filter()-->利用指定的函数确定是否在返回的数组中包含某一项
function count(arr, item) {
    var count = arr.filter(function(a) {
    return a === item;   //返回true的项组成的数组
    });
    return count.length;
}
//map()-->对数组中的每一项进行给定函数,
//返回每次函数条用的结果组成的数组;
function count(arr, item) {
      var count = 0;
      arr.map(function(a) {
        if(a === item) {
          count++;
      }
      });
      return count;
}
    //for循环
function count(arr, item) {
      var count = 0;
      for(var i=0; i
         if(arr[i] === item) {
           count++;
         }
}
      return count;
}
   //reduce()-->从数组的第一项开始,逐个遍历到最后;
function count(arr, item) {
     var count = arr.reduce(function(prev, curr) {
       return curr === item ? prev+1 : prev;
     }, 0);
     return count;
}
    //forEach()-->对数组中的每一项运行传入的函数
function count(arr, item) {
     var count = 0;
     arr.forEach(function(a) {
       a === item ? count++ : 0;
     });
     return count;
}

11、找出数组 arr 中重复出现过的元素 
将传入的数组arr中的每一个元素value当作另外一个新数组b的key,然后遍历arr去访问b[value],若b[value]不存在,则将b[value]设置为1,若b[value]存在,则将其加1。可以想象,若arr中数组没有重复的元素,则b数组中所有元素均为1;若arr数组中存在重复的元素,则在第二次访问该b[value]时,b[value]会加1,其值就为2了。最后遍历b数组,将其值大于1的元素的key存入另一个数组a中,就得到了arr中重复的元素。
function duplicates(arr) {
//声明两个数组,a数组用来存放结果,b数组用来存放arr中每个元素的个数
var a = [],b = [];
//遍历arr,如果以arr中元素为下标的的b元素已存在,则该b元素加1,否则设置为1
for(var i = 0; i < arr.length; i++){
if(!b[arr[i]]){
b[arr[i]] = 1;
continue;
}
b[arr[i]]++;
}
//遍历b数组,将其中元素值大于1的元素下标存入a数组中
for(var i = 0; i < b.length; i++){
if(b[i] > 1){
a.push(i);
}
}
return a;
}

function duplicates(arr) {
 var result = [];
    arr.forEach(function(elem){
       if(arr.indexOf(elem) !=arr.lastIndexOf(elem) && result.indexOf(elem) == -1){
           result.push(elem);
       }
    });
    return result;
}

12、在数组 arr 中,查找值与 item 相等的元素出现的所有位置 
//filter
function findAllOccurrences(arr, target) {
    var result=[];
    arr.filter(function(item,index){
        return item===target&&result.push(index);
    });
    return result;
}
//for
function findAllOccurrences(arr, target) {
    var result=[];
    for(var i=0;i
        if(arr[i]===target){
            result.push(i); //每一个if语句都可以用一个||代替或者三目运算符arr[i]!==target || result.push(i) ;
        }
    }
    return result;
}
//lastIndexOf+slice/splice
function findAllOccurrences(arr, target) {
    var result=[],index=arr.lastIndexOf(target);
    while(index>-1){
        result.push(index);
        arr.splice(index,1);//arr=arr.slice(0,index);
        index=arr.lastIndexOf(target);
    }
    return result;
}
//indexOf
function findAllOccurrences(arr, target) {
    var result=[],index=arr.indexOf(target);
    while(index>-1){
        result.push(index);
        index=arr.indexOf(target,index+1);
    }
    return result;
}

13、实现一个打点计时器,要求
1)、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2)、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3)、第一个数需要立即输出
setInterval() 方法会按照指定周期不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。注意第一个数需要立即输出即可。
function count(start, end) {
   //立即输出第一个值
  console.log(start++);
  var timer = setInterval(function(){
    if(start <= end){
       console.log(start++);
    }else{
       clearInterval(timer);
    }
  },100);
   //返回一个对象
  return {
    cancel : function(){
      clearInterval(timer);
    }
  };
}

14、实现函数 makeClosures,调用之后满足如下条件:
1)返回一个函数数组 result,长度与 arr 相同
2)运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同 
简单的描述闭包:如果在函数func内部声明函数inner,然后在函数外部调用inner,这个过程即产生了一个闭包。
题目要求的是返回一个函数数组,如果在循环中直接写result[i] = function(){return fn(arr[i]);}或者result.push(function(){return fn(arr[i]);}),最终的结果是不正确的,因为在每次迭代的时候,那样的语句后面的方法并没有执行,只是创建了一个函数体为“return fn(arr[i]);”的函数对象而已,当迭代停止时,i为最终迭代停止的值,在函数被调用时,i依旧为最终迭代停止的值,因此无法返回正确的结果。
为了解决这个问题,需要声明一个匿名函数,并立即执行它。
function(num){return function(){return fn(arr[num]); }; }(i),函数执行后,i立即传入并被内部函数访问到,因此就能得到正确的结果。闭包允许你引用存在于外部函数中的变量。
下面的代码使用的是forEach循环
function makeClosures(arr, fn) {
  var result = [];
     arr.forEach(function(e){
         result.push(function(num){
             return function(){
                 return fn(num);
             };
         }(e));
     });
     return result;
 }
看到题目我首先想到的是使用闭包时因为作用域链引来的副作用,(闭包只能得到包含函数中变量的最后一个值)如果直接用下面第一种写法会导致result中每个函数的参数都是arr[arr.length],在《JavaScript高级程序设计》书中提到的最典型的解决此问题的方法就是用一个立即执行的匿名函数代替闭包负值给数组,这个匿名函数有一个参数num,因为函数参数是按值传递的所以传递给num的就是当前for循环的值。接下来的是根据其他小伙伴的解决方案进行的总结,提供给新来的小伙伴一个总结,页方便自己以后看
此外ES5提供了bind方法,apply(),call(),bind()方法在使用时如果已经对参数进行了定义
又因为在此问题中用的是数组并且需要的是arr[i]所以用forEach()方法就不用考虑第一段中提到的问题
//这种是错误的写法会导致result中每个函数的参数都是arr[arr.length]
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i
result[i] = function(){
return fn(arr[i]); 
};
}
return result;
}
//参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i
result[i] = function(num){
return function(){
return fn(num);
}
}(arr[i]);
}
return result;
}
//使用ES5的bind()方法
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i
result[i] = fn.bind(null,arr[i]);
}
return result;
}
//使用forEach()
function makeClosures(arr, fn) {
var result = new Array();
arr.forEach(function(curr){
result.push(function(){return fn(curr)});
})
return result;
}

15、已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致 
partial(sayIt, 'Hello', 'Ellie')('!!!');首先执行partial(sayIt, 'Hello', 'Ellie'),将参数传入,然后返回函数result与('!!!')组合成result('!!!')执行。于是,可以在result函数里调用fn,因为函数的参数固定为三个,因此可以用call方法去调用函数fn。
function partial(fn, str1, str2) {
var result = function(str3){
return fn.call(this, str1, str2, str3);
}
return result;
}

16、函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。 
本题考查的是对于arguments的使用,arguments能获得函数对象传入的参数组,类似与一个数组,能够通过length获取参数个数,能通过下标获取该位置的参数,但是它不能使用forEach等方法。本题先通过arguments.length获得参数个数,然后循环求和,得出结果。
function useArguments() {
   /*
   因为参数数量不定,可以先获取参数个数arguments.length
   然后循环求值
  */
  //声明一个变量保存最终结果
  var sum = 0;
  //循环求值
  for(var i = 0; i < arguments.length; i++){
      sum += arguments[i];
  }
  return sum;
 }

function useArguments() {
    var arr=Array.prototype.slice.call(arguments) //把arguments类数组转化为数组
    return eval(arr.join("+")); //求和
}

function useArguments() {
    var result = Array.prototype.reduce.call(arguments,function(a,b){return a+b;});
    return result;
}

function useArguments() {
    return Array.prototype.slice.call(arguments).reduce(function(pre,cur,i,a){
        return pre + cur;
    });
}

17、实现函数 callIt,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数 
因为arguments并非真正的数组,因此要获得callIt的第一个参数之后的所有参数,不能直接使用slice方法截取,需要先将arguments转换为真正的数组才行。有两种常见的方法,一是使用slice方法:var args = Array . prototype . slice . call ( arguments );二是循环遍历逐一填入新数组。在获得了args之后,就可以调用apply来执行传入的函数参数。
function callIt(fn) {
     //将arguments转化为数组后,截取第一个元素之后的所有元素
    var args = Array.prototype.slice.call(arguments,1);
     //调用fn
    var result = fn.apply(null,args);
    return result;
}
// slice
function callIt(fn) {
    var arr = [].slice.call(arguments, 1);
     /* 将arguments转成数组并只截取从1开始之后的所有元素 */
    return fn.apply(this, arr);
// shift
function callIt(fn) {
    return [].shift.call(arguments).apply(null, arguments);
     /* [].shift.call(arguments)返回了第一个参数fn, 因为这里fn等价于arguments[0] */
}
// ES6语法糖
const callIt = (fn, ...args) => fn(...args);

18、实现函数 partialUsingArguments,调用之后满足如下条件:
1)返回一个函数 result
2)调用 result 之后,返回的结果与调用函数 fn 的结果一致
3)fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数 
arguments不能用slice方法直接截取,需要先转换为数组,var args = Array.prototype.slice.call(arguments);合并参数可以使用concat方法,并且也需要将arguments先转换为数组才能使用concat进行合并。最用使用apply执行传入的函数即可。
function partialUsingArguments(fn) {
     //先获取p函数第一个参数之后的全部参数
     var args = Array.prototype.slice.call(arguments,1);
      //声明result函数
     var result = function(){
          //使用concat合并两个或多个数组中的元素
         return fn.apply(null, args.concat([].slice.call(arguments)));
     }
     return result;
 }

19、已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件:
1)返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数)
2)调用 a 之后,返回一个函数 b, b 的 length 属性值为 1
3)调用 b 之后,返回一个函数 c, c 的 length 属性值为 1
4)调用 c 之后,返回的结果与调用 fn 的返回值一致
5)fn 的参数依次为函数 a, b, c 的调用参数 
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。简单理解题目意思,就是指,我们将预定义的函数的参数逐一传入到curryIt中,当参数全部传入之后,就执行预定义函数。于是,我们首先要获得预定义函数的参数个数fn.length,然后声明一个空数组去存放这些参数。返回一个匿名函数接收参数并执行,当参数个数小于fn.length,则再次返回该匿名函数,继续接收参数并执行,直至参数个数等于fn.length。最后,调用apply执行预定义函数。
function curryIt(fn) {
     //获取fn参数的数量
     var n = fn.length;
      //声明一个数组args
     var args = [];
     //返回一个匿名函数
     return function(arg){
         //将curryIt后面括号中的参数放入数组
         args.push(arg);
         //如果args中的参数个数小于fn函数的参数个数,
         //则执行arguments.callee(其作用是引用当前正在执行的函数,这里是返回的当前匿名函数)。
         //否则,返回fn的调用结果
         if(args.length < n){
          return arguments.callee;
         }else return fn.apply("",args);
     }
 }
function curryIt(fn) {
    var length = fn.length,args = [];
    var result =  function (arg){
         args.push(arg);
         length --;
         if(length <= 0 ){
            return fn.apply(this, args);
        } else {
             return result;
         }
    }
     
    return result;
}

20、获取数字 num 二进制形式第 bit 位的值。注意:
1)bit 从 1 开始
2)返回 0 或 1
3)举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1 
function valueAtBit(num, bit) {
var s=num.toString(2);
return s[s.length-bit];
}

21、给定二进制字符串,将其换算成对应的十进制数字
parseInt方法可以将其它进制转换为十进制,只需要给该方法传入需要转换的字符串和该字符串的进制表示两个参数即可。
function base10(str) {
return parseInt(str,2).toString(10);
}

22、将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。 
function convertToBinary(num) {
     //转换为2进制格式
     var s = num.toString(2);
      //获得2进制数长度
     var l = s.length;
     if(l<8){
         //声明一个字符串用于补满0
         var s1 = "0000000";
         var s2 = s1.slice(0,8-l);
         s = s2+s; 
     }
     return s;
 }
function convertToBinary(num) {
    var str = num.toString(2);
    while(str.length < 8) {
     str = "0" + str;
    } 
    return str;
}

23、给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。
这是原型链问题。访问一个对象的方法或者是属性,首先会在该对象中寻找,如果找到则返回,如果没找到,则在其原型链上面向上寻找,直至基原型,如还未找到,则返回undefined。将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量,只需要在constructor的原型上面添加greeting属性,并指定值。
function alterObjects(constructor, greeting) {
  constructor.prototype.greeting = greeting;
}
function alterObjects(constructor, greeting) {
  if(typeof constructor != 'function') throw('alterObjects():arguments error, should be function');
  constructor.prototype.greeting = greeting;
}

24、找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
1)返回数组,格式为 key: value
2)结果数组不要求顺序 
可以使用for-in来遍历对象中的属性,hasOwnproperty方法能返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性,该属性必须为对象本身的属性。
function iterate(obj) {
  var arr = [];
  //使用for-in遍历对象属性
  for(var key in obj){
     //判断key是否为对象本身的属性
    if(obj.hasOwnProperty(key)){
       //将属性和值按格式存入数组
      arr.push(key+": "+obj[key]);
    }
  }
  return arr;
}
function iterate(obj) {
  return Object.getOwnPropertyNames(obj).map(function(key){
     return key+": "+obj[key];
  });
}

25、给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false 
判断字符串中是否含有数字,可以用正则表达式。/\d/可以匹配字符串中的数字字符,用test方法可以检测。
function containsNumber(str) {
  var b = /\d/;
  return b.test(str);
}

function containsNumber(str) {
    return str.split("").filter(function(item){
                return !isNaN(parseInt(item))
            }).length ? true : false;
}
/*只要匹配到一个数字,就返回true*/
function containsNumber(str) {
    var pattern=/\d/g;
    if(str.match(pattern))
        return true;
    else
        return false;
}
function containsNumber(str) {
    var res =  str.search(/\d/);
    if (res > -1) {
        return true;
    } else {
        return false;
    }
}

26、给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false 
在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,\1就是引用第一个分组,\2就是引用第二个分组。将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。
function containsRepeatingLetter(str) {
   return /([a-zA-Z])\1/.test(str);
}
function containsRepeatingLetter(str) {
      var reg=/[a-zA-Z]/;
      for(var i=0,len=str.length;i
          if(str.charAt(i)==str.charAt(i+1) && reg.test(str.charAt(i))){
              return true;
          }
      }
     return false;
}

27、给定字符串 str,检查其是否以元音字母结尾
1)元音字母包括 a,e,i,o,u,以及对应的大写
2)包含返回 true,否则返回 false 
首先确定元音集合[a,e,i,o,u],然后是以元音结尾,加上$,最后通配大小写,加上i。因此正则表达式为:/[a,e,i,o,u]$/i,最后用test方法去检测字符串str
function endsWithVowel(str) {
  return /[a,e,i,o,u]$/i.test(str);
}
function endsWithVowel(str) {
  var reg = /(a|o|e|i|u)$/gi;
  return reg.test(str);
}
function endsWithVowel(str) {
    return str && ("aeiouAEIOU".indexOf(str[str.length-1]) > -1);
}

28、给定字符串 str,检查其是否包含 连续3个数字 
1)如果包含,返回最新出现的 3 个数字的字符串
2)如果不包含,返回 false 
题目描述有问题,实际考察的是字符串中是否含有连续的三个任意数字,而不是三个连续的数字。依题,若存在连续的三个任意数字,则返回最早出现的三个数字,若不存在,则返回false。因此需要用到match方法,match()返回的是正则表达式匹配的字符串数组,连续的三个任意数字用正则表达式表示为/\d{3}/。
function captureThreeNumbers(str) {
//声明一个数组保存匹配的字符串结果
var arr = str.match(/\d{3}/);
//如果arr存在目标结果,则返回第一个元素,即最早出现的目标 结果
if(arr)
return arr[0];
else return false;
}
function captureThreeNumbers(str) {
 var arr = str.match(/\d{3}/);
 return (arr && arr[0]) || false;
}
function captureThreeNumbers(str) {
     var res = str.match(/\d{3}/g);
     return res? res[0]:false;
}

29、给定字符串 str,检查其是否符合如下格式
1)XXX-XXX-XXXX
2)其中 X 为 Number 类型
本题需要注意格式,开头^和结尾$必须加上来限定字符串,3个数可表示为\d{3},4个数则为\d{4},{n}表示前面内容出现的次数。正则表达式可写作/^\d{3}-\d{3}-\d{4}$/,有相同部分\d{3}-,因此也可写作/^(\d{3}-){2}\d{4}$/
function matchesPattern(str) {
  return/^(\d{3}-){2}\d{4}$/.test(str);
}
function matchesPattern(str) {
 return/^(\d{3}-){2}\d{4}$/.test(str);
}

30、给定字符串 str,检查其是否符合美元书写格式
1)以 $ 开始
2)整数部分,从个位起,满 3 个数字用 , 分隔
3)如果为小数,则小数部分长度为 2
4)正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3 
本题注意点有必须是USD格式,以$开头,数字结尾,$和小数点的转义。
首先,开头必是$,而正则表达式中$表示结尾,需要进行转义,因此开头为^\$
然后$后必然接数字,并且最少一位,最多三位数,可用{m,n}表示,最少m位,最多n位,因此此段为\d{1,3}
接着,后面如还有数,则必然有,分隔,并且后面必有3个数,类似于,XXX的格式会出现0或者n次,因此此段可表示为(,\d{3})*
最后,如有小数部分,则注意对小数点进行转义,此段可表示为(\.\d{2})?
因此,最后的正则表达式为/^\$\d{1,3}(,\d{3})*(\.\d{2})?$/
使用test方法去检测str
function isUSD(str) {
  return /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/.test(str);
}
function isUSD(str) {
  var re = /^\$([1-9]\d{0,2}(,\d{3})*|0)(\.\d{2})?$/;
   return re.test(str);
}

31、数组去重
1)创建一个新的数组存放结果
2)创建一个空对象
3)for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个 元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。
说明:至于如何对比,就是每次从原数组中取出一个元素,然后到对象中去访问这个属性,如果能访问到值,则说明重复。
Array.prototype.unique3 = function(){
 var res = [];
 var json = {};
 for(var i = 0; i < this.length; i++){
  if(!json[this[i]]){
   res.push(this[i]);
   json[this[i]] = 1;
  }
 }
 return res;
}
var arr = [112,112,34,'你好',112,112,34,'你好','str','str1'];
alert(arr.unique3());
1)先将原数组进行排序
2)检查原数组中的第i个元素 与 结果数组中的最后一个元素是否相同,因为已经排序,所以重复元素会在相邻位置
3)如果不相同,则将该元素存入结果数组中
Array.prototype.unique2 = function(){
 this.sort(); //先排序
 var res = [this[0]];
 for(var i = 1; i < this.length; i++){
  if(this[i] !== res[res.length - 1]){
    res.push(this[i]);
  }
 }
 return res;
}
var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0]
alert(arr.unique2());
Array.prototype.unique1 = function () {
var n = []; //一个新的临时数组
for (var i = 0; i < this.length; i++) //遍历当前数组 {
//如果当前数组的第i已经保存进了临时数组,那么跳过, //否则把当前项push到临时数组里面
if (n.indexOf(this[i]) == -1) n.push(this[i]);
}
return n;
}
Array.prototype.unique2 = function(){
var n = {},r=[]; //n为hash表,r为临时数组
for(var i = 0; i < this.length; i++) //遍历当前组 {
if (!n[this[i]]) //如果hash表中没有当前项
{
n[this[i]] = true; //存入hash表
r.push(this[i]); //把当前数组的当前项push到临时数组里面
}
}
return r;
}

Array.prototype.unique3 = function(){
var n = [this[0]]; //结果数组
for(var i = 1; i < this.length; i++) //从第二项开始遍历 {
//如果当前数组的第i项在当前数组中第一次出现的位置不是i,
//那么表示第i项是重复的,忽略掉。否则存入结果数组
if (this.indexOf(this[i]) == i)
n.push(this[i]);
}
return n;
}


你可能感兴趣的:(前端,javascript)