1.javascript数组原型方法。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>jstest</title> 6 </head> 7 <body> 8 <script> 9 var arr = ["1","2","3"]; 10 arr.baz = "baz"; 11 console.log(arr); // 数组也是对象,添加属性后,并不会改变它的长度; 12 var myObj = { 13 a:2 14 } 15 console.log( Object.getOwnPropertyDescriptor(myObj,"a")); 16 Object.defineProperty(myObj,"a",{ 17 value:3, 18 writable:false, 19 enumerable:true, 20 configurable:true 21 }) 22 23 myObj.a = 4; 24 console.log(myObj.a); //3 定义属性描述不可写,无法修改值 25 //属性描述符里有get和set两个,分别表示读写。 26 27 //当configurable为false时,属性没法修改 ,没法delete删除,有个例外,可以把writable由true改为false。 28 // 只要属性是可配置的,就可以用 Object.defineProperty()设置属性描述符。 29 30 /*要设置对象或属性不可变: 31 1.常量对象:结合 writable:fasle和configurable:false创建常量属性(不可修改,重定义,删除)。 32 2.禁止扩展:禁止对象添加新属性,保留已有属性,使用 Object.preventExtensions(obj); 33 3.密封:Object.seal() 会创建一个密封的对象,实际上是在现有对象的基础上调用preventExtensions, 34 并把所有现有属性标记为false; 35 4.冻结:Object.freeze() 会创建一个冻结对象,他在原有对象的基础上,调用seal()并把所有数据访问的属性标记为 36 writable:false,这是级别最高的不可变性。 37 */ 38 var b={ a:undefined } 39 console.log(b.a); //undefined 40 console.log(b.b); //undefined 41 42 /* 43 上面的两个结果都为undefined,区别在于内部的get操作。 44 可以判断属性的存在性,去区别这两种情况: 45 */ 46 console.log("a" in b); //true 47 console.log("b" in b); //false 48 // 或者 49 console.log(b.hasOwnProperty("a")); //true 50 console.log(b.hasOwnProperty("b")); //false 51 /* 52 上面两种方式的区别在于: 53 1.in会检查属性是否存在于对象或其原型链中, 54 2.hasOwnProperty只检查属性是否存在于对象中,不检查原型链。 55 56 注意:in操作符检查的是属性,不是值, 2 in [1,2]并不是true, 57 */ 58 59 /* 60 可枚举性:设为false的时候,它不会出现在对象属性的循环遍历中。下面例子: 61 */ 62 var obj= {} 63 Object.defineProperty(obj,"a",{ 64 value:2, 65 enumerable:true 66 }); 67 console.log(obj.a); 68 Object.defineProperty(obj,"b",{ 69 value:3, 70 enumerable:false 71 }) 72 console.log(obj.b); 73 // 检测存在性 74 console.log("a" in obj); 75 console.log("b" in obj); 76 77 console.log( obj.hasOwnProperty("a")); 78 console.log(obj.hasOwnProperty("b")); 79 80 // 进行循环 81 for(var k in obj){ 82 console.log(k,obj[k]) // 结果 a 2 83 } 84 /* 以上结果表明 enumerable设为false的时候,属性仍存在,但不会被遍历。 85 同时,for in 循环,用来遍历数组的话,有可能会把数组中的非数字索引遍历到,所以 86 数组循环,最好用传统的for循环,看下面例子: 87 */ 88 var arr = [1,2,3] 89 arr.baz = "baz"; 90 for(var k in arr){ 91 console.log(k,arr[k]); 92 } 93 /*结果 0 1 94 1 2 95 2 3 96 baz baz 97 */ 98 /* 99 forEach() 会遍历数组中的所有值,并忽略回调函数的返回值。 100 */ 101 var arr = [1,2,3,4,5] 102 arr.forEach(function(value){ 103 console.log(value,"forEach"); 104 }) 105 106 //every() 函数一直运行,直到回调函数返回false值,或者遍历结束。 107 //这里需要返回值,是说每次循环都要有返回值,也就是说 108 //if条件不满足的时候,也要进行return 109 var i = 0; 110 arr.every(function(value){ 111 i+=value; 112 console.log("every",value) 113 // return value<3 114 if(i>20){ 115 return false 116 }else{ 117 return true 118 } 119 }) 120 // 跟上边的every()类似,some() 函数会在返回值是真的时候停止。 简单例子: 121 arr.some(function(value){ 122 console.log(value,"some"); 123 return value>2 124 }) 125 126 //不通过下标,直接遍历数组:ES6 方法; 127 for(var v of arr){ 128 console.log(v,"for...of"); 129 } 130 //for...of... 实际上是通过对象的迭代器对象,调用next()方法来实现遍历的。 131 //下面用原生内置的 @@iterator手动遍历: 132 var arr = [1,2,3,4]; 133 var it = arr[Symbol.iterator](); 134 console.log(it.next().value,"iterator"); 135 console.log(it.next().value,"iterator"); 136 console.log(it.next().value,"iterator"); 137 console.log(it.next().value,"iterator"); 138 console.log(it.next().value,"iterator"); 139 140 141 //给对象定义迭代器:举例: 142 var obj = { 143 a:2, 144 b:3 145 } 146 Object.defineProperty(obj,Symbol.iterator,{ 147 enumerable:false, 148 writable:false, 149 configurable:true, 150 value:function(){ 151 var o = this,idx = 0,ks = Object.keys(o); 152 return { 153 next:function(){ 154 return { 155 value:o[ks[idx++]], 156 done:(idx>ks.length) 157 } 158 } 159 } 160 } 161 }) 162 //根据定义好的iterator 进行手动迭代: 163 var it = obj[Symbol.iterator](); 164 console.log(it.next(),"手动迭代") 165 console.log(it.next(),"手动迭代") 166 console.log(it.next(),"手动迭代") 167 //for of 遍历 168 for(var v of obj){ 169 console.log(v,"forof"); 170 } 171 172 // 你可以定义一个无限迭代: 173 var randoms = { 174 [Symbol.iterator]:function(){ 175 return { 176 next:function(){ 177 return { value:Math.random()} 178 } 179 } 180 } 181 }; 182 var randoms_pool = []; 183 for(var n of randoms){ 184 randoms_pool.push(n); 185 if(randoms_pool.length ===100){ 186 console.log(randoms_pool); 187 break; 188 } 189 } 190 //这个迭代器会生成无数个随机数,因此添加break阻止。 191 192 //原型 193 var obj = { 194 a:2 195 }; 196 var newobj = Object.create(obj) 197 198 console.log("a" in newobj); //true 199 console.log(newobj.hasOwnProperty("a")); //false 200 // 上面的结果表明,a属性,存在于newobj的原型链中,但不属于它本身。 201 newobj.a++; 202 console.log(newobj.a); //3 203 console.log(obj.a); //2 204 //上面就是一个隐式屏蔽,下层不会改变上层的值,还有一个情况就是,上层会改变下层的值 205 206 /* 207 我们只需要两个对象就可以判断他们之间的关系,举例: 208 b是否出现在c的原型链中: b.isPrototypeOf(c) 209 也可以直接获取一个对象的原型链: 210 */ 211 var new2obj = Object.create(newobj); 212 console.log(Object.getPrototypeOf(new2obj)); 213 </script> 214 </body> 215 </html>