关于foreach:对象数组的遍历方法总结

遍历对象办法规范形容返回值特点for...inES5遍历对象的所有可枚举属性可枚举原型链上可枚举蕴含原型链上的可枚举属性可breakObject.keys()ES5返回对象所有可枚举属性可枚举返回的数组中的值都是字符串(不是也转string)Object.getOwnPropertyNames()ES6对象本身的所有属性名可枚举不可枚举蕴含不可枚举的属性Object.getOwnPropertySymbols()ES6返回对象本身的Symbol属性组成的数字,不蕴含字符串振兴symbol属性的值(可枚举和不可枚举) Reflect.ownKeys()ES6返回一个数组,蕴含对象本身的所有属性可枚举不可枚举symbol类型 Object.values()ES8返回对象所有可枚举属性值的数组可枚举 Object.entries()ES8返回对象本身可枚举属性的键值对数组可枚举 js分为函数对象和一般对象,每个对象都有__proto__属性,只有函数对象才有prototype属性 Object.defineProperties()办法间接在一个对象上定义新的属性或批改现有属性,并返回该对象。该办法默认enumerable为false 可枚举属性:外部“可枚举(enumerable)”标记设置为true的属性不可枚举属性:与可枚举属性相同 var obj=function(){ this.name = "张三"; this.age = 10}; //构造函数var newobj = new obj(); //创立实例,实例对象会继承构造函数的原型属性obj.prototype.friend = "李四"; //在原型上增加属性//在对象newobj上定义新的属性Object.defineProperties(newobj,{ "city":{ value: "杭州", enumerable: true,//是否为枚举属性 }, "height":{ value: '2m', enumerable: false,//是否为枚举属性 }, [Symbol('sex')]:{ value: 'symbol_sex', enumerable: true },})for(var i in newobj){console.log(i)} //name age city friendObject.keys(newobj) //["name", "age", "city"]Object.getOwnPropertyNames(newobj) //["name", "age", "city", "height"]Object.ownKeys(newobj) //["name", "age", "city", "height", Symbol(sex)]Object.values(newobj) // ["张三", 10, "杭州"]Object.entries(newobj) //[["name", "张三"],["age", 10],["city", "杭州"]]Object.getOwnPropertySymbols(newobj) //[Symbol(sex)]遍历数组办法规范特点breakforEach()ES5不扭转原数组无返回值否map()ES5不扭转原始数据返回一个新数组否for ofES6 是for await ofES9异步遍历是filter()ES6不扭转原数组返回符合条件的元素否some()every()ES6不扭转原数组返回true或false否reduce()ES6累加器不扭转原数组否find()ES6返回第一个符合条件的元素不扭转原数组否findIndex()ES6返回第一个符合条件的索引值不扭转原数组否keys()ES6返回数组的索引值否values()ES6返回数组的元素否entries()ES6返回数组的键值对否//for await offunction Gen (time) { return new Promise((resolve,reject) => { setTimeout(function () { resolve(time) },time) })}async function test () { let arr = [Gen(2000),Gen(100),Gen(3000)] for await (let item of arr) { console.log(Date.now(),item) if(item===100){ break; } }}// 1648631137863 2000// 1648631137863 100test()//keys()、values()、entries()var arr = ["周一","周二","周三"];var iterator1 = arr.keys();var iterator2 = arr.values() var iterator3 = arr.entries() for (let item of iterator1) { console.log(item); // 0 1 2}for (let item of iterator2) { console.log(item); // 周一 周二 周三}for (let item of iterator3) { console.log(item); //[0,"周一"] [1,"周二"] [2,"周三"]}其它循环办法表列 B特点breakfor循环代码块肯定的次数 是while当指定的条件为 true 时循环指定的代码块先判断再执行否do...while直反复直到指定的条件为false先执行再判断否性能比拟var data=[];for(var i=0;i<1000000;i++){ data.push(i)}//forEachconsole.time('forEach')var result1=[];data.forEach(item=>{ result1.push(item);})console.timeEnd('forEach') //39ms//mapconsole.time('map')var result2=[];data.map(item=>{ result2.push(item);})console.timeEnd('map') //33.ms//for ofconsole.time('for...of')var result3=[];for(var item of data){ result3.push(item)}console.timeEnd('for...of') //25.ms//for inconsole.time('for...in')var result4=[];for(var item in data){ result4.push(data[item])}console.timeEnd('for...in') //169ms//forconsole.time('for循环')var result5=[];for(var i=0;i<data.length;i++){ result5.push(data[item])}console.timeEnd('for循环') //17ms

March 31, 2022 · 1 min · jiezi

PHP细节:foreach、(汉子)字符串反转、isset,empty用法区别以及0、‘’、null之间关系

一、foreach第一题://1.for循环执行几次//for($i=0;$i=1;$i++){// echo $i;//}$i==1条件很成立,死循环for($i=0;$i==1;$i++){ echo $i;}由于条件$i==1条件不成立,所以for循环不执行第二题:class SomeClass{ private $properties = []; public $j; public function __set($name, $value) { $this->properties[$name] = $value; } public function __get($name) { return $this->properties[$name]; }}$obj = new SomeClass();$obj->name = ‘phpgod’;$obj->age = 2;$obj->gender = ‘male’;//$obj->j=0;$l = null;var_dump($obj->name);//output:string(6) “phpgod"var_dump($obj->j); //nullvar_dump(isset($obj->j));//由于$j没有赋值,为空null,所以返回false//var_dump($obj->properties);var_dump(isset($obj->name));//私有或者保护属性不能被调用,false//output:bool(false),你的答案对了吗?为什么第三题:foreach和取地址运算符&$arr = [1,2,3,4,5,8];foreach($arr as &$v) { //nothing todo. echo $v.’<br />’;}//&是取地址运算符,$v = &$a; 这时$v就是$a变量在内在中的存储地址,$v改变$a同样会改变,因为是一个地址var_dump($arr); //1,2,3,4,5,8foreach($arr as &$v) { //nothing todo. var_dump($arr); echo $v.’<br />’;}var_export($arr); //1,2,3,4,5,5&是取地址运算符,$v = &$a; 这时$v就是$a变量在内在中的存储地址,$v改变$a同样会改变,因为是一个地址参考文档1:对数组两次foreach的使用陷阱PHP foreach原理详解二、(汉子)字符串反转包含汉字字符串乱码PHP面试题,题目很短,也很常见,但更容易出错,题目如下如何实现字符串翻转? 第一反应,当然是strrev函数啦,这么容易的题目还放在面试里考,真不嫌麻烦啊?但是看了网上的答案后,发现自己错了~~~ strrev函数对英文很好用,直接可以实现字符串翻转,但是面对中文呢?肯定都是乱码,对于这样的问题有很多,比如strstr,substr等函数都是这样的。还好PHP提供了mb_类的函数实现不同编码、不同语言之间的相互转换等操作。下面是我写的PHP字符串翻转函数(mb_类的函数需要开启一个mb_string实现)。解决方案代码:<?phpheader(“content-type:text/html;charset=utf-8”);/** strrev() 函数反转字符串。 语法 strrev(string) 参数 描述 string 必需。规定要反转的字符串。 *//**此函数的作用是反转中文字符串mb_strlen() 获取字符的长度mb_substr() 获取字符的单个元素krsort() 按照键值逆序排序数组,对关联数组按照键名进行降序排序Array ( [8] => 国 [7] => 中 [6] => h [5] => s [4] => i [3] => l [2] => g [1] => n [0] => E ) English中国->国中hsilgnE(ksort()对关联数组按照键名进行升序排序)implode() 将数组拼接为字符串explode() 使用字符串分隔字符串 */function str_rev_gb($str){ //判断输入的是不是utf8类型的字符,否则退出 if(!is_string($str)||!mb_check_encoding($str,‘UTF-8’)){ exit(“输入类型不是UTF8类型的字符串”); } $array=array(); //将字符串存入数组 $l=mb_strlen($str,‘UTF-8’);//在mb_strlen计算时,选定内码为UTF8,则会将一个中文字符当作长度1来计算 for($i=0;$i<$l;$i++){ $array[]=mb_substr($str,$i,1,‘UTF-8’); } //反转字符串 krsort($array); //拼接字符串 $string=implode($array); return $string;}$str1 = “Englist”;$str2 = “English中国”;$str3 = “Eng中lish国”;$str4 = “中华人民共和国”;echo ‘直接用PHP自带strrev函数反转:’.’<br />’;echo $str1.”->".strrev($str1)."<br>";echo $str2."->".strrev($str2)."<br>";echo $str3."->".strrev($str3)."<br>";echo $str4."->".strrev($str4)."<br>";echo ‘<br />’;echo $str1."->".str_rev_gb($str1)."<br>";echo $str2."->".str_rev_gb($str2)."<br>";echo $str3."->".str_rev_gb($str3)."<br>";echo $str4."->".str_rev_gb($str4)."<br>";运行结果:直接用PHP自带strrev函数反转:Englist->tsilgnEEnglish中国->��學�hsilgnEEng中lish国->���hsil���gnE中华人民共和国->��匒居呰溺䎍學�Englist->tsilgnEEnglish中国->国中hsilgnEEng中lish国->国hsil中gnE中华人民共和国->国和共民人华中需要注意的是,mb_strlen并不是PHP核心函数,使用前需要确保在php.ini中加载了php_mbstring.dll,即确保“extension=php_mbstring.dll”这一行存在并且没有被注释掉,否则会出现未定义函 数的问题。参考文档:PHP 实现字符串翻转(包含中文汉字)参考:// 处理汉字function strReverseMb($str) { $revStr = ‘’; if (is_string($str) && mb_check_encoding($str, “UTF-8”)) { $len = mb_strlen($str); for ($i = $len-1; $i>=0; $i–) { $revStr .= mb_substr($str, $i, 1, “UTF-8”); } } return $revStr;}php官方文档strrev函数最下面给出了支持utf-8的方案:function utf8_strrev($str){ preg_match_all(’/./us’, $str, $ar); return join(’’,array_reverse($ar[0]));}三、isset、empty、if用法区别以及0、‘’、null之间关系3.1 empty用法bool empty ( mixed var)如果 var 是非空或非零的值,则 empty() 返回 FALSE。换句话说,""、0、“0”、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的,如果 var 为空,则返回 TRUE3.2 isset()isset – 检测变量是否设置描述bool isset ( mixed var [, mixed var [, …]])如果 var 存在则返回 TRUE,否则返回 FALSE。如果已经使用 unset() 释放了一个变量之后,它将不再是 isset()。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是一个 NULL 字节(“0”)并不等同于 PHP 的 NULL 常数。注意:如果变量不存在(或者unset()释放一个变量后),isset()和empty()都不会报错;is_null(),is_numeric(),if会报错is_numeric 检测变量是否为数字或数字字符串;is_null正好是isset的反结果,我们可以把它看成是!isset,是isset的一个逆操作。警告: isset() 只能用于变量,因为传递任何其它参数都将造成解析错误。若想检测常量是否已设置,可使用 defined()函数。用法:注意defined(""),如果没有双引号,则会警告:undefined constant websiteif(defined(“website”)){ echo “true”;}else{ echo “false”;}3.3 0、‘’、null之间相等关系if(’’ == null && ’’ == 0 && null == 0 && 0 ==‘0’) echo ‘if’;if(’’ == ‘0’ || null == ‘0’ ) echo ‘if2’;结论:’’ ,null , 0 ,‘0’互相相等;’’,null不等于'0’ ...

March 8, 2019 · 2 min · jiezi

mybatis 使用foreach 数据类型不对导致报错

起因使用mybatis动态sql进行遍历条件的时候报了下面这个错误:Caused by: java.lang.IllegalStateException: Type handler was null on parameter mapping for property ‘__frch_item_0’. It was either not specified and/or could not be found for the javaType (com.test.Report) : jdbcType (null) combination. at org.apache.ibatis.mapping.ParameterMapping$Builder.validate (ParameterMapping.java:117) at org.apache.ibatis.mapping.ParameterMapping$Builder.build (ParameterMapping.java:104) at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping (SqlSourceBuilder.java:123) at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken (SqlSourceBuilder.java:67) at org.apache.ibatis.parsing.GenericTokenParser.parse (GenericTokenParser.java:69) at org.apache.ibatis.builder.SqlSourceBuilder.parse (SqlSourceBuilder.java:45) at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql (DynamicSqlSource.java:44) at org.apache.ibatis.mapping.MappedStatement.getBoundSql (MappedStatement.java:292) at org.apache.ibatis.executor.CachingExecutor.query (CachingExecutor.java:81) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList (DefaultSqlSession.java:148) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList (DefaultSqlSession.java:141) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:498) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke (SqlSessionTemplate.java:434) at com.sun.proxy.$Proxy57.selectList (Unknown Source) at org.mybatis.spring.SqlSessionTemplate.selectList (SqlSessionTemplate.java:231)<select id=“getById” parameterType=“map” resultType=“Report”> select * from test where orderid in <foreach collection=“idlist” item=“item” index=“index” open="(" separator="," close=")"> #{item} </foreach> </select>怎么找都没找到原因,最后发现这个sql之所以报错并不是这个sql写错了,而是传入的参数报错了,我认为参数是这个样子的:{ “name”:“张三”, “idlsit”:{1,2,3}}最后发现,参数是这个样子的的:{ “name”:“张三”, “idlsit”:{Report对象,Report对象,Report对象}}看到这里可能会觉得怎么可能出现这种问题,编译都不会通过,但是通过特殊的情况确实产生了,我的代码如下: List<String> idList = reportDao.getIdList(start, end); if (null != idList && idList.size() >= 1) { result = orderReportDao.getById(idList, start); }sql: <select id=“getIdList” parameterType=“map” resultType=“Report”>//这个返回值类型错了 select id from test_id </select> <select id=“getById” parameterType=“map” resultType=“Report”> select * from test where orderid in <foreach collection=“idlist” item=“item” index=“index” open="(" separator="," close=")"> #{item} </foreach> </select>实际上在执行过程中getIdList的返回类型错了,但是没有报错误,返回值List < String > idList实际上是List < Report > idList,这竟然没有报错,可能反射有关。 ...

February 28, 2019 · 1 min · jiezi

for of, for in, forEach比较

forEachforEach无法中途跳出forEach循环,break、continue和return都不奏效。for infor…in 循环只遍历可枚举属性。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototype和String.prototype的不可枚举属性,例如 String 的 indexOf() 方法或 Object的toString()方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。for…in不应该用于迭代一个 Array,其中索引顺序很重要。for in 循环的输出顺序问题先遍历出整数属性(integer properties,按照升序),然后其他属性按照创建时候的顺序遍历出来。var obj = { a:1, ‘2’:1, ‘1’:1, d:1, c:1, ‘3’:1}obj.b=66;for (var key in obj) { console.log(key ); } //“1”, “2”, “3”, “a”, “d”, “c”, “b"Object.keys(obj); //[“1”, “2”, “3”, “a”, “d”, “c”, “b”]Object.keys()和for in 具有相同的排列顺序for of有着同for…in一样的简洁语法,但是没有for…in那些缺点。不同于forEach方法,它可以与break、continue和return配合使用。提供了遍历所有数据结构的统一操作接口。

February 26, 2019 · 1 min · jiezi