javascript练习题中遇到的小技巧

来源:互联网 发布:网络造谣法律规定 编辑:程序博客网 时间:2024/06/05 10:05

1.练习遇到JSON对象数组的迭代,常规会想着采用for循环,但使用javascript数组迭代方法更简单有效。

 function lookUp(firstName, prop){  var temp = contacts.filter(function(item){    return item.firstName == firstName;  });  //此处的contacts是JSON对象数组。  if(temp.length){      return temp[0][prop] ? temp[0][prop] : 'No such property';  }  return 'No such contact';}lookUp("Harry","lastName");

2.移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回

function removeWithoutCopy(arr, item) {  for(var i=0;i<arr.length;i++){      if(arr[i]===item){          arr.splice(i,1);          i--;//注意此处i一定要自减,这样当此次循环完成I++执行后i的值不变,才能符合移除了一项的情况。      }  }    return arr;}

3.删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组

function truncate(arr) {    var newArr=new Array();    newArr=arr.slice(0);    newArr.pop();    return newArr;}

使用数组的slice()方法,基于调用他的数组中的一个或者多各项创建一个新的数组,当传入一个参数时返回参数指定位置开始(包括指定位置)到数组所有项;如果有两个参数,返回起始位置和结束位置(不包括结束位置的项)之间的所有项。此方法不会影响原始数组,因而可以用来创建数组的副本,即slice(0)的情况。

4.合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组

function concat(arr1, arr2) {    var newArr=[];    newArr=arr1.concat(arr2);    return newArr;}

注意此处用concat()函数,基于当前数组对象创建一个新的对象,此方法会首先创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组;如果不传参则复制调用它的数组并返回副本。

5.找出数组 arr 中重复出现过的元素

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

此题使用forEach()循环,在数组每一项上运行特定函数。注意forEach()循环中函数的if条件。查找所给的val的位置,如果从前向后查找的位置索引与从后向前查找的不同,则说明该val重复出现,并且这个val在存储重复值的数组中找不到时,说明是一个新的重复值。同时符合这两个条件加入结果数组。

6.将数组 arr 中的元素作为调用函数 fn 的参数

function argsAsArray(fn, arr) {    return fn.apply(this,arr);    }

每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法都是在特定的作用域中调用函数,实际上等同于设置被调用函数体内的this对象。
apply()方法两个参数,一个是调用apply()的函数的作用域,另一个是参数数组,可以是Array实例也可以是arguments对象。
call()方法与apply()的区别在于,传给函数的参数必须列举出来,例如

function callSum(num1,num2){  return sum.call(this,num1,num2);}

这两个方法最强大的地方在于能够扩充函数作用域

sayColor.call(window);

将sayColor函数的作用域改为window

7.实现函数 makeClosures,调用之后满足如下条件(1)、返回一个函数数组 result,长度与 arr 相同 (2)、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同

function makeClosures(arr, fn) {    var result = new Array();    for(var i=0;i<arr.length;i++){        result[i] = function(num){            return function(){                return fn(num);            };        }(arr[i]);    }    return result;}

此题考点为闭包与变量的问题。由于闭包只能取得包含函数中任何变量的最后一个值,闭包保存的是整个变量的对象。如果这样写的话就导致了这个问题

function createFunctions(){  var result=[];  for(var i=0;i<10;i++){    result[i]=function(){      return i;      };   }   retrurn result;}

这个函数执行下来,result里面的每个值都是10
改进办法是:不要把闭包直接赋值给数组,定义一个匿名函数,并将立即执行改匿名函数的结果赋值给数组。这个匿名函数的参数为num,也就是最终的函数要返回的值。在调用每个匿名函数时,传入变量i,由于参数按值传递,就把i当前的值赋值给了num,而匿名函数内部又创建并返回了一个访问num的闭包。这样,result数组中的每个函数都有自己num变量的副本(每个函数保存的num副本的值是当时i的值),这样就解决了上述的问题。

function createFunctions(){   var result=[];   for(var i=0;i<10;i++){       result{i]=function(num){           return function(){                return num;           };       }(i);   }   return result;}

8.函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
这里重点就是类数组对象:arguments –接收所有传入函数的参数值的类数组对象,它有两个特点跟数组很像,1.可以用下标访问每个元素2.具有length属性。
这里最好先通过Array.prototype.slice.call(我们的类数组对象) 将其转换成一个真正的数组对象,然后再遍历求和即可。

function useArguments() {   var aArguments=Array.prototype.slice.call(arguments);       var sum=0;       aArguments.forEach(function(value){           sum+=value;       });       return sum;   } 

9.实现函数 partialUsingArguments,调用之后满足如下条件: (1)返回一个函数 result (2)调用 result 之后,返回的结果与调用函数 fn 的结果一致 (3)fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数

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;}

注意此处[].slice.call(arguments),[]是Array的一个实例,[].slice会在Array的原型链上找到slice方法,相当于Array.prototype.slice.call(argument).
9.给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。

function alterObjects(constructor, greeting) {     constructor.prototype.greeting = greeting; }

属于原型链的问题,访问一个对象的属性或者方法,首先在改对象的实例上面找,找到则返回,未找到则在原型链上找,直到基类原型,找到返回,未找到返回undfined。

10.找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)(1)、返回数组,格式为 key: value(2)、结果数组不要求顺序

function iterate(obj) {     var arr = [];     for(var key in obj){         if(obj.hasOwnProperty(key)){             arr.push(key+": "+obj[key]);         }     }     return arr; }

for-in循环时,返回的是所有能够通过对象访问的属性(可枚举的属性),无论属性存在于实例还是原型上。hasOwnProPerty()方法可以检测属性存在于实例还是原型,这个方法继承与Object,给定属性存在于对象实例时返回true。

11.给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false

function containsRepeatingLetter(str) {     return /([a-zA-Z])\1/.test(str); }

()进行分组,\1代表第一个分组,\2是第二个分组。具体可见http://www.cnblogs.com/-ShiL/archive/2012/04/06/Star201204061009.html(目前不太明白正则,之后补充)

12.给定字符串 str,检查其是否以元音字母结尾 (1)、元音字母包括 a,e,i,o,u,以及对应的大写(2)、包含返回 true,否则返回 false

function endsWithVowel(str) {    return  /.[aeiou]$/i.test(str);}

以…结尾加$,不区分大小写加i.

13.给定字符串 str,检查其是否符合如下格式:XXX-XXX-XXXX,其中 X 为 Number 类型

function matchesPattern(str) { return/^(\d{3}-){2}\d{4}$/.test(str);}
开头^和结尾$必须加上来限定字符串,3个数可表示为\d{3}4个数则为\d{4}{n}表示前面内容出现的次数。正则表达式可写作/^\d{3}-\d{3}-\d{4}$/,有相同部分\d{3}-,可写作/^(\d{3}-){2}\d{4}$/ 
 14.给定字符串 str,检查其是否符合美元书写格式:、以 $ 开始;整数部分,从个位起,满 3 个数字用 , 分隔 ;如果为小数,则小数部分长度为 2 ;正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12或者 $34,344.3
function isUSD(str) { return /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/.test(str);}

USD格式,以和小数点的转义。
首先,开头必是表示结尾,需要进行转义,因此开头为^$
然后m,n,mn\d1,33XXX0n(,\d3)(.\d2)?/$\d1,3(,\d3)(.\d2)?/
使用test方法去检测str

0 0
原创粉丝点击