整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          javascript數組與對象

          組和對象

          什么是對象,其實就是一種類型,即引用類型。而對象的值就是引用類型的實例。在ECMAScript 中引用類型是一種數據結構,用于將數據和功能組織在一起。它也常被稱做為類,但 ECMAScript 中卻沒有這種東西。雖然 ECMAScript 是一門面向對象的語言,卻不具備傳統面向對象語言所支持的類和接口等基本結構。


          一.Object 類型

          到目前為止,我們使用的引用類型最多的可能就是 Object 類型了。雖然 Object 的實例不具備多少功能,但對于在應用程序中的存儲和傳輸數據而言,它確實是非常理想的選擇。創建 Object 類型有兩種。一種是使用 new 運算符,一種是字面量表示法。

          1.使用 new 運算符創建 Object

          var box = new Object();

          box.name = '大圣網絡';

          box.age = 28;

          2.new 關鍵字可以省略

          var box = Object();

          3.使用字面量方式創建 Object

          var box = {

          name : '大圣網絡',

          age : 28

          };

          4.屬性字段也可以使用字符串形式

          var box = {

          'name' : '大圣網絡',

          'age' : 28

          };

          5.使用字面量及賦值方式

          var box = {}; //字面量方式聲明空的對象

          box.name = '大圣網絡'; //點符號給屬性復制

          box.age = 28;

          6.兩種屬性輸出方式

          alert(box.age);

          alert(box['age']);

          7.給對象創建方法

          var box = {

          run : function () { //對象中的方法

          return '運行';

          }

          }

          alert(box.run()); //調用對象中的方法

          8.使用 delete 刪除對象屬性

          delete box.name; //刪除屬性

          在實際開發過程中,一般我們更加喜歡字面量的聲明方式。因為它清晰,語法代碼少 ,而且還給人一種封裝的感覺。字面量也是向函數傳遞大量可選參數的首選方式。

          function box(obj) { //參數是一個對象

          if (obj.name != undefined) alert(obj.name); //判斷屬性是否存在

          if (obj.age != undefined) alert(obj.age);

          }

          box({ //調用函數傳遞一個對象

          name : '大圣',

          age : 28

          });

          二. Array 類型

          除了 Object 類型之外,Array 類型是 ECMAScript 最常用的類型。而且 ECMAScript 中的 Array 類型和其他語言中的數組有著很大的區別。 雖然數組都是有序排列, 但 ECMAScript中的數組每個元素可以保存任何類型。ECMAScript 中數組的大小也是可以調整的。創建 Array 類型有兩種方式:第一種是 new 運算符,第二種是字面量。

          1.使用 new 關鍵字創建數組

          var box = new Array(); //創建了一個數組

          var box = new Array(10); //創建一個包含 10 個元素的數組

          var box = new Array('李炎恢',28,'教師','鹽城'); //創建一個數組并分配好了元素

          2.以上三種方法,可以省略 new 關鍵字。

          var box =Array();

          3 使用字面量方式創建數組

          var box = []; //創建一個空的數組

          var box = ['大圣',28,'金箍棒']; //創建包含元素的數組

          4.使用索引下標來讀取數組的值

          alert(box[2]); //獲取第三個元素

          box[2] = '學生'; //修改第三個元素

          box[4] = '計算機編程'; //增加第五個元素

          5.使用 length 屬性獲取數組元素量

          alert(box.length) //獲取元素個數

          box.length = 10; //強制元素個數

          box[box.length] = 'JS 技術'; //通過 length 給數組增加一個元素

          6.創建一個稍微復雜一點的數組

          var box = [

          {

          name : '李炎恢',

          age : 28,

          run : function () {

          return 'run 了';

          }

          },

          ['馬云','馬化騰',new Object()],

          '江蘇',

          25+25,

          new Array(1,2,3)

          ];

          alert(box);

          三. 對象中的方法

          轉換方法

          對象或數組都具有toLocaleString()、 toString()和valueOf()方法。 其中toString()和valueOf()無論重寫了誰,都會返回相同的值。數組會講每個值進行字符串形式的拼接,以逗號隔開。

          var box = ['小學生',8,'計算機編程']; //字面量數組

          alert(box); //隱式調用了 toString()

          alert(box.toString()); //和 valueOf()返回一致

          alert(box.toLocaleString()); //返回值和上面兩種一致

          默認情況下,數組字符串都會以逗號隔開。如果使用 join()方法(相當于php函數的implode),則可以使用不同的分隔符來構建這個字符串。

          var box = ['小學生', 8, '計算機編程'];

          alert(box.join('|')); //小學生|8|計算機編程

          棧方法

          ECMAScript 數組提供了一種讓數組的行為類似于其他數據結構的方法。也就是說,可以讓數組像棧一樣,可以限制插入和刪除項的數據結構。棧是一種數據結構(后進先出),也就是說最新添加的元素最早被移除。而棧中元素的插入(或叫推入)和移除(或叫彈出),只發生在一個位置——棧的頂部。ECMAScript 為數組專門提供了 push()和 pop()方法。push()方法可以接收任意數量的參數,把它們逐個添加到數組的末尾,并返回修改后數組的長度。而 pop()方法則從數組末尾移除最后一個元素,減少數組的 length 值,然后返回移除的元素。

          var box = ['大圣', 500, '打妖怪']; //字面量聲明

          alert(box.push('斗戰勝佛')); //數組末尾添加一個元素,并且返回長度

          alert(box); //查看數組

          box.pop(); //移除數組末尾元素,并返回移除的元素

          alert(box); //查看元素

          隊列方法

          棧方法是后進先出,而列隊方法就是先進先出。列隊在數組的末端添加元素,從數組的前端移除元素。通過 push()向數組末端添加一個元素,然后通過 shift()方法從數組前端移除一個元素。ECMAScript 還為數組提供了一個 unshift()方法,它和 shift()方法的功能完全相反。

          var box = ['大圣', 500, '打妖怪'];

          alert(box.shift()); //移除數組開頭元素,并返回移除的元素

          alert(box); //查看數組

          var box = ['大圣', 500, '打妖怪'];

          alert(box.unshift('a','b')); //數組開頭添加兩個元素

          alert(box); //查看數組

          alert(box.pop()); //移除數組末尾元素,并返回移除的元素

          alert(box); //查看數組

          重排序方法

          數組中已經存在兩個可以直接用來排序的方法:reverse()和 sort()。

          reverse() 逆向排序

          var box = [1,2,3,4,5]; //數組

          alert(box.reverse()); //逆向排序方法,返回排序后的數組

          alert(box); //源數組也被逆向排序了,說明是引用

          sort() 從小到大排序

          var box = [4,1,7,3,9,2]; //數組

          alert(box.sort()); //從小到大排序,返回排序后的數組

          alert(box); //源數組也被從小到大排序了

          sort 方法的默認排序在數字排序上有些問題,因為數字排序和數字字符串排序的算法是一樣的。我們必須修改這一特征,修改的方式,就是給 sort(參數)方法傳遞一個函數參數。這點可以參考手冊說明。

          操作方法

          ECMAScript 為操作已經包含在數組中的元素提供了很多方法。 concat()方法可以基于當前數組創建一個新數組。 slice()方法可以基于當前數組獲取指定區域元素并創建一個新數組 。splice()主要用途是向數組的中部插入元素。

          var box = ['大圣網絡', 28, '中國']; //當前數組

          var box2 = box.concat('計算機編程'); //創建新數組,并添加新元素

          alert(box2); //輸出新數組

          var box = ['大圣網絡', 28, '中國'];; //當前數組

          var box2 = box.slice(1); //box.slice(1,3),2-4 之間的元素

          alert(box2); //28,中國

          splice 中的刪除功能:

          var box = ['大圣網絡', 28, '中國']; //當前數組

          var box2 = box.splice(0,2); //截取前兩個元素

          alert(box2); //返回截取的元素

          alert(box); //當前數組被截取的元素被刪除

          splice 中的插入功能:

          var box = ['大圣網絡', 28, '中國']; //當前數組

          var box2 = box.splice(1,0,'計算機編程','安徽'); //沒有截取,但插入了兩條

          alert(box2); //在第 2 個位置插入兩條

          alert(box); //輸出

          splice 中的替換功能:

          var box = ['大圣網絡', 28, '中國']; //當前數組

          var box2 = box.splice(1,1,100); //截取了第 2 條,替換成 100

          alert(box2); //輸出截取的 28

          alert(box); //輸出數組

          Array 對象

          Array 對象用于在變量中存儲多個值:

          var cars = ["Saab", "Volvo", "BMW"];

          第一個數組元素的索引值為 0,第二個索引值為 1,以此類推。

          更多有關JavaScript Array參考手冊請參考 JavaScript Array 對象手冊。

          Array 對象屬性

          方法描述
          concat()連接兩個或更多的數組,并返回結果。
          every()檢測數值元素的每個元素是否都符合條件。
          filter()檢測數值元素,并返回符合條件所有元素的數組。
          indexOf()搜索數組中的元素,并返回它所在的位置。
          join()把數組的所有元素放入一個字符串。
          lastIndexOf()返回一個指定的字符串值最后出現的位置,在一個字符串中的指定位置從后向前搜索。
          map()通過指定函數處理數組的每個元素,并返回處理后的數組。
          pop()刪除數組的最后一個元素并返回刪除的元素。
          push()向數組的末尾添加一個或更多元素,并返回新的長度。
          reverse()反轉數組的元素順序。
          shift()刪除并返回數組的第一個元素。
          slice()選取數組的的一部分,并返回一個新數組。
          some()檢測數組元素中是否有元素符合指定條件。
          sort()對數組的元素進行排序。
          splice()從數組中添加或刪除元素。
          toString()把數組轉換為字符串,并返回結果。
          unshift()向數組的開頭添加一個或更多元素,并返回新的長度。
          valueOf()返回數組對象的原始值。

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!

          么把一個對象當做數組使用?

          我們知道在JS中對象和數組的操作方式是不一樣的,但是我們可以通過封裝,給對象加一層包裝器,讓它可以和數組擁有同樣的使用方式。我們主要借助Object.keys()Object.values()Object.entries()Proxy

          Object.keys

          看一下MDN上的解釋:

          Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和正常循環遍歷該對象時返回的順序一致。

          也就是Object.keys可以獲取對象的所有屬性名,并生成一個數組。

          var obj = { a: 0, b: 1, c: 2 };
          console.log(Object.keys(obj));
          // console: ['a', 'b', 'c']
          

          Object.values

          看一下MDN上的解釋:

          Object.values()方法返回一個給定對象自身的所有可枚舉屬性值的數組,值的順序與使用for...in循環的順序相同 ( 區別在于 for-in 循環枚舉原型鏈中的屬性 )。

          Object.values()返回一個數組,元素是對象上找到的可枚舉屬性值。

          var obj = { foo: 'bar', baz: 42 };
          console.log(Object.values(obj));
          // ['bar', 42]
          

          Object.entries

          看一下MDN上的解釋:

          Object.entries()方法返回一個給定對象自身可枚舉屬性的鍵值對數組,其排列與使用 for...in 循環遍歷該對象時返回的順序一致(區別在于 for-in 循環還會枚舉原型鏈中的屬性)。

          Object.entries()返回一個數組,元素是由屬性名和屬性值組成的數組。

          const obj = { foo: 'bar', baz: 42 };
          console.log(Object.entries(obj));
          // [ ['foo', 'bar'], ['baz', 42] ]
          

          Proxy

          Proxy是JS最新的對象代理方式,用于創建一個對象的代理,從而實現基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數調用等)。

          使用Proxy可以封裝對象的原始操作,在執行對象操作的時候,會經過Proxy的處理,這樣我們就可以實現數組操作命令。

          基礎 get 示例

          const handler = {
            get: function(obj, prop) {
              return prop in obj ? obj[prop] : 37;
            }
          }
          const p = new Proxy({}, handler);
          p.a = 1;
          p.b = undefined;
          console.log(p.a, p.b)
          console.log('c' in p, p.c)
          

          以上示例的中,當對象中不存在屬性名時,默認返回值為37

          無操作轉發代理

          使用Proxy包裝原生對象生成一個代理對象p,對代理對象的操作會轉發到原生對象上。

          let target = {};
          let p = new Proxy(target, {});
          p.a = 37;   // 操作轉發到目標
          console.log(target.a);    // 37. 操作已經被正確地轉發
          

          我們要實現以下幾個函數:forEachmapfilterreduceslicefindfindKeyincludeskeyOflastKeyOf

          實現數組函數

          forEach

          數組中的forEach函數定義:arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

          數組中的forEach需要傳入一個函數,函數的第一個參數是當前操作的元素值,第二個參數是當前操作的元素索引,第三個參數是正在操作的對象。

          對于對象,我們將參數定為:currentValue、key、target。我們可以使用Object.keys來遍歷對象。

          Object.keys(target).forEach(key => callback(target[key], key, target))

          這里需要targetcallback參數,我們通過函數封裝一下

          function forEach(target, callback) {
            Object.keys(target).forEach(key => callback(target[key], key, target))
          }
          

          這樣我們就可以使用以下方式調用:

          const a = {a: 1, b: 2, c: 3}
          forEach(a, (v, k) => console.log(`${k}-${v}`))
          // a-1
          // b-2
          // c-3
          

          通過Proxy封裝:

          const handler = {
            get: function(obj, prop) {
              return forEach(obj)
            }
          }
          const p = new Proxy(a, handler)
          p.forEach((v, k) => console.log(`${k}-${v}`))
          

          以上方式當然是不行的,我們主要看最后一句,其執行方式和數組的forEach完全相同,我們在調用Proxy封裝的對象時,獲取數據時,會調用get函數,第一個參數為原生對象,第二個參數為屬性名-forEach,在這里就要修改我們的forEach函數了。首先p.forEach的參數是一個函數,因此我們代理對象的返回值需要接收一個函數作為參數,因此修改如下:

          function forEach(target) {
            return (callback) => Object.keys(target).forEach(key => callback(target[key], key, target))
          }
          

          因此完成代碼為:

          function forEach(target) {
            return (callback) => Object.keys(target).forEach(key => callback(target[key], key, target))
          }
          const handler = {
            get: function(obj, prop) {
              return forEach(obj)
            }
          }
          const a = {a: 1, b: 2, c: 3}
          const p = new Proxy(a, handler)
          p.forEach((v, k) => console.log(`${k}-${v}`))
          // a-1
          // b-2
          // c-3
          

          我們應該把以上代碼封裝為模塊,方便對外使用:

          const toKeyedArray = (obj) => {
            const methods = {
              forEach(target) {
                return (callback) => Object.keys(target).forEach(key => callback(target[key], key, target));
              }
            }
            const methodKeys = Object.keys(methods)
            const handler = {
              get(target, prop) {
                if (methodKeys.includes(prop)) {
                  return methods[prop](target)
                }
                return Reflect.get(...arguments)
              }
            }
            return new Proxy(obj, handler)
          }
          const a = { a: 1, b: 2, c: 3}
          const p = toKeyedArray(a)
          p.forEach((v, k) => console.log(`${k}-${v}`))
          

          以上是forEach的實現和封裝,其他函數的實現方式類似。

          全部源碼如下:

          const toKeyedArray = (obj) => {
            const methods = {
              forEach(target) {
                return (callback) => Object.keys(target).forEach(key => callback(target[key], key, target));
              },
              map(target) {
                return (callback) =>
                  Object.keys(target).map(key => callback(target[key], key, target));
              },
              reduce(target) {
                return (callback, accumulator) =>
                  Object.keys(target).reduce(
                    (acc, key) => callback(acc, target[key], key, target),
                    accumulator
                  );
              },
              forEach(target) {
                return callback =>
                  Object.keys(target).forEach(key => callback(target[key], key, target));
              },
              filter(target) {
                return callback =>
                  Object.keys(target).reduce((acc, key) => {
                    if (callback(target[key], key, target)) acc[key] = target[key];
                    return acc;
                  }, {});
              },
              slice(target) {
                return (start, end) => Object.values(target).slice(start, end);
              },
              find(target) {
                return callback => {
                  return (Object.entries(target).find(([key, value]) =>
                    callback(value, key, target)
                  ) || [])[0];
                };
              },
              findKey(target) {
                return callback =>
                  Object.keys(target).find(key => callback(target[key], key, target));
              },
              includes(target) {
                return val => Object.values(target).includes(val);
              },
              keyOf(target) {
                return value =>
                  Object.keys(target).find(key => target[key] === value) || null;
              },
              lastKeyOf(target) {
                return value =>
                  Object.keys(target)
                    .reverse()
                    .find(key => target[key] === value) || null;
              }
            }
            const methodKeys = Object.keys(methods)
            const handler = {
              get(target, prop) {
                if (methodKeys.includes(prop)) {
                  return methods[prop](target)
                }
                const [keys, values] = [Object.keys(target), Object.values(target)];
                if (prop === 'length') return keys.length;
                if (prop === 'keys') return keys;
                if (prop === 'values') return values;
                if (prop === Symbol.iterator)
                  return function* () {
                    for (value of values) yield value;
                    return;
                  };
                return Reflect.get(...arguments)
              }
            }
            return new Proxy(obj, handler)
          }
          const x = toKeyedArray({ a: 'A', b: 'B' });
          x.a;          // 'A'
          x.keys;       // ['a', 'b']
          x.values;     // ['A', 'B']
          [...x];       // ['A', 'B']
          x.length;     // 2
          // Inserting values
          x.c = 'c';    // x = { a: 'A', b: 'B', c: 'c' }
          x.length;     // 3
          // Array methods
          x.forEach((v, i) => console.log(`${i}: ${v}`)); // LOGS: 'a: A', 'b: B', 'c: c'
          x.map((v, i) => i + v);                         // ['aA', 'bB, 'cc]
          x.filter((v, i) => v !== 'B');                  // { a: 'A', c: 'c' }
          x.reduce((a, v, i) => ({ ...a, [v]: i }), {});  // { A: 'a', B: 'b', c: 'c' }
          x.slice(0, 2);                                  // ['A', 'B']
          x.slice(-1);                                    // ['c']
          x.find((v, i) => v === i);                      // 'c'
          x.findKey((v, i) => v === 'B');                 // 'b'
          x.includes('c');                                // true
          x.includes('d');                                // false
          x.keyOf('B');                                   // 'b'
          x.keyOf('a');                                   // null
          x.lastKeyOf('c');                               // 'c'
          

          JS系列1-布爾陷阱以及如何避免


          主站蜘蛛池模板: 久久精品无码一区二区三区免费| 国产精品久久无码一区二区三区网| 日本精品视频一区二区三区| 精品国产亚洲一区二区三区在线观看 | 国产伦精品一区二区三区四区 | 成人精品一区二区三区电影| 亚洲AV无码一区二区二三区入口 | 国产一区二区三区在线免费观看| 久久99国产精品一区二区| 亚洲Av高清一区二区三区| 亚洲一区无码中文字幕| 国产99精品一区二区三区免费| 成人无码精品一区二区三区| 无码毛片视频一区二区本码 | 香蕉免费一区二区三区| 精品女同一区二区三区免费播放| 亚洲AV无码一区二区三区牲色| 麻豆一区二区在我观看 | 国产成人无码一区二区在线播放 | 日韩制服国产精品一区| 国产av福利一区二区三巨| 波多野结衣中文字幕一区二区三区 | 一区二区三区精品视频| 色一情一乱一伦一区二区三区| 韩国精品一区视频在线播放| 无码人妻av一区二区三区蜜臀| 国产精品电影一区二区三区| 国产精品亚洲一区二区三区 | 末成年女AV片一区二区| 亚洲AV无码一区二区三区在线| 亚洲一区二区三区91| 亚洲一区精彩视频| 亚洲a∨无码一区二区| 麻豆国产在线不卡一区二区| 日韩一区二区三区在线| 丰满岳妇乱一区二区三区| 中文字幕一区二区在线播放 | 亚洲香蕉久久一区二区| 亚洲无码一区二区三区| 国产一区二区在线视频播放| 成人无码一区二区三区|