编程这么多年,如果每次写遍历代码都用for循环,真的对不起JavaScript语言~ObjectTraversal为了方便测试对象遍历,我下面定义一个测试对象obj。测试对象//为对象设置三个自定义属性(可枚举)Object.prototype.userProp='userProp';Object.prototype.getUserProp=function(){returnObject.prototype.userProp;};//定义一个Object,隐式继承自Object.prototypevarobj={name:'percy',age:21,[Symbol('symbolproperty')]:'symbolProp',unEnumerable:'Iamanon-enumerableproperty',技能:['html','css','js'],getSkills:function(){returnthis.skills;}};//设置unEnumerable属性为不可枚举属性Object.defineProperty(obj,'unEnumerable',{enumerable:false});在ES6之后,有以下5种方法可以遍历对象的属性。for...in:遍历对象自身和继承的可枚举属性(不包括Symbol类型的属性)for(letkeyinobj){console.log(key);控制台日志(obj.key);//错误的样式console.log(obj[key]);//对的样式}不要用for...in来遍历数组,虽然可以遍历,但是如果给Object.prototype设置了可枚举的属性,这些属性也会被遍历到,因为数组也是一种的对象。Object.keys(obj):返回一个数组,包括对象本身所有可枚举的属性(不继承)(不包括Symbol类型的属性)Object.keys(obj);//["name","age","skills","getSkills"]Object.getOwnPropertyNames(obj):返回一个包含对象自身所有属性的数组(不包括Symbol类型的属性,不包括继承的属性,但包括非-enumerableproperties)Object.getOwnPropertyNames(obj);//["name","age","unEnumerable","skills","getSkills"]Object.getOwnPropertySymbols(obj):返回包含所有属性的数组对象本身的Symbol类型(不包括Inherited属性)Object.getOwnPropertySymbols(obj);//[Symbol(symbolproperty)]Reflect.ownKeys(obj):返回一个包含对象自身所有属性(包括Symbol类型的属性)的数组,和不可枚举的属性,但不包括继承的属性)Reflect.ownKeys(obj);//["name","age","unEnumerable","skills","getSkills",Symbol(symbolattribute)]上面5方法遍历一个对象的属性遵循同样顺序的属性遍历规则。首先遍历所有名为数值的属性,按数字排序,然后遍历所有名为字符串的属性,按生成时间排序。***遍历所有名为Symbol值的属性,按照生成时间排序。如何判断某个属性是否是对象本身的属性?在obj中使用in运算符(不严谨,其实是判断属性是否在对象的原型链上)'age';//o中的true'userProp'bj;//true(userProp是obj原型链上的一个属性)'name'inObject;//true//上面之所以为真,是因为Object是一个构造函数,而函数恰好有一个name属性Object.name;//'对象'Array.name;//'Array'使用hasOwnProperty(),该方法只会检测对象上的属性,不会检测原型链上的属性obj.hasOwnProperty('age');//trueobj.hasOwnProperty('技能');//trueobj.hasOwnProperty('userProp');//false但它仍然有缺点。例子~//使用Object.create()创建一个新对象,这个对象没有任何原型链varobj2=Object.create(null,{name:{value:'percy'},age:{value:21},技能:{值:['html','css','js']}});obj2.hasOwnProperty('名称');//报错obj2.hasOwnProperty('skills');//报错是针对上面的情况,我们用更完整的方案来解决。使用Object.prototype.hasOwnProperty.call(obj,'prop'…)Object.prototype.hasOwnProperty.call(obj2,'name');//trueObject.prototype.hasOwnProperty.call(obj2,'skills');//trueObject.prototype.hasOwnProperty.call(obj2,'userProp');//false数组遍历数组其实就是对象,所以你可以使用上面的任何一种方法来遍历对象(但要注意尺度)。此外,数组还有其他的遍历方式。最基本的for循环和while循环遍历(缺陷是多加了一个计数变量)ES6引入:for...of,这个计数变量已经没有了,但是不够简洁(我就不介绍了这里有详细的,后面会写)for(letvalueofarr){console.log(value);}下面是几个数组的内置遍历方法Array.prototype.forEach():执行提供的函数Array...索引varwords=["one","two","three","four"];words.forEach(function(word){console.log(word);if(word==="two"){words.shift();}});//one//two//fourArray.prototype.map():返回一个新数组,每个元素都是回调函数返回的值Array.prototype.map(callback(currentValue,index,array){//做一些thing}[,thisArg]);``````js//map的一个坑[1,2,3].map(parseInt);//[1,NaN,NaN]//提示map(currentValue,index,array)//parseInt(value,base)一些有用的数组内置方法(类似于map,回调函数的参数就是那3个)Array.prototype.every(callback[,thisArg]):测试数组的每个元素是否通过,如果回调函数的测试通过则返回true,否则返回false(本质上如果回调返回的值功能每次都是真的,然后every()返回true,否则为false)Array.prototype.filter(callback[,thisArg]):返回一个新数组,其元素为原数组中通过测试的元素(即如果回调函数返回true,对应的元素会进入新数组)Array.prototype.find(callback[,thisArg]):返回第一个通过测试的元素Array.prototype.findIndex(callback[,thisArg]):类似abovefunction,除了this是ReturnindexArray.prototype.some(callback[,thisArg]):和find()类似,只是不返回元素,只返回一个boolean值只要找到通过测试的,returntrueArray.prototype.reduce(callback,[initialValue]):习惯上调用一个累加器函数,对数组的每个元素执行一个回调函数,最后返回一个值(this值为最后一次调用回调函数时返回的值)该函数的回调函数有4个参数accumulator:回调函数最后一次调用返回的值currentValue:当前正在处理的值currentIndex数组initialValue:可选,其值使用第一次调用callback的第一个参数Array.prototype.reduceRight(callback[,initialValue]):用法与上述函数相同,只是遍历方向正好相反//一些relatedcases//归约数组累加乘法等操作[1,10,5,3,8].reduce(function(accumulator,currentValue){returnaccumulator*currentValue;});//1200//数组扁平化[[0,1],[2,3],[4,5]]。reduce(function(a,b){returna.concat(b);});//[0,1,2,3,4,5][[0,1],[2,3],[4,5]]。reduceRight(function(a,b){returna.concat(b);});//[4,5,2,3,0,1]综上所述,以上函数的共性是通过各个回调函数的返回值进行逻辑运算或判断。回调函数可以写成更简洁的箭头函数(推荐),可以通过Array.prototype.map.call(str,callback)的形式来操作字符串varstr='123,hello';//反转字符串Array.prototype.reduceRight.call(str,function(a,b){返回a+b;});//olleh,321//过滤字符串,只保留小写字母Array.prototype.filter.call('123,hello',function(a){return/[a-z]/.test(a);}).join('');//hello//使用map遍历字符串(这个例子显然不是很好*_*)Array.prototype.map.call(str,function(a){returna.toUpperCase();});//["1","2","3",",","H","E","L","L","O"]底条想说的是让我们使用更简洁的语法(如内置函数)遍历数组,从而消除循环结构
