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>