2019年12月28日 星期六

jQuery 的工具函數測試

jQuery 的優點除了提供好用的選擇器可用來操控網頁內容外, 還提供了許多工具函數 (utilities) 可用來操作 DOM 物件以外的 Javascript 物件, 不僅可簡化 Javascript 程式碼, 也彌補了 Javascript 內建函數之不足, 其主要功能有 :
  • 陣列/物件操作
  • 字串處理
  • Ajax 請求
  • 表單請求參數處理
這些工具函數都是定義於 jQuery 名稱空間 (name space) 中的頂層函數, 並不是某個 DOM 元素的 jQuery 物件之方法, 因此這些函數是用 $ 物件直接呼叫, 它們被用來操作 Javascript 物件而不是 DOM 物件. 操作 DOM 元素的功能通常被設計為 jQuery 物件之方法.

jQuery 說明文件參考 :

https://jquery.com/
https://www.jquery123.com/


一. 陣列與物件處理 : 

jQuery 工具函數中與陣列或物件處理相關之函數如下表 :


 jQuery 陣列/物件工具函數 說明
 $.each(array/object, callback) 迭代陣列元素或物件屬性給回呼函數, 傳回新物件或陣列
 $.grep(array, callback[, invert]) 以回呼函數過濾陣列, 以通過之元素組成新陣列傳回
 $.map(array, callback) 迭代陣列元素至回呼函數, 以傳回值組成新陣列傳回
 $.makeArray(object) 將物件轉成陣列後傳回
 $.merge(array1, array2) 將兩個陣列合併後傳回
 $.unique(array) 去除陣列內重複之元素後傳回新陣列
 $.inArray(value, array) 檢查 value 是否為陣列 array 之元素 (true/false)
 $.isArray(param) 檢查參數是否為 Javascript 陣列
 $.isPlainObject(param) 檢查參數為用 {} 或 new Object() 建立之物件


1. $.each() 函數 :

此函數是一個通用的迭代 (iteration) 函數, 可以同時迭代陣列, 類陣列 (例如代表函數引數的 arguments 物件), 或物件. 其介面如下 :

$.each(collection, callback)

第一個參數為欲迭代的對象容器, 包含陣列, 類陣列, 與物件. 這些容器由不定個數的元素組成, 為了存取這些容器的元素, Javascript 提供了下列迴圈或方法來迭代這些容器的元素 :
  • for 迴圈 : 用來迭代字串, 陣列或類陣列物件之元素
  • for in 迴圈 : 用來迭代字串, 陣列元素或物件屬性
  • for of 迴圈 : 用來迭代字串, 陣列元素或物件屬性
  • forEach 方法 : 用來迭代陣列元素 
其中 forEach 與 for of 比較新, forEach 是 ECMAScript 5 (ES5) 才加入的功能 (只能用在陣列), 而 for of 則是為了修補 for in 之不足而在 ECMAScript 2015 (ES6) 才加入的功能, 有些較舊的瀏覽器並不支援 (例如 IE8 與 Firefox 1.8),  jQuery 的 $.each() 函數不僅可同時用在陣列與物件, 而且解決了跨瀏覽器與版本問題.


範例 1 : Javascript 的迭代迴圈 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr=["a", "b", "c"];
        var obj={name:"tony", gender:"male", age:18};
        document.write('arr=["a", "b", "c"]<br>');     
        var str="Hello World!";
        document.write('arr=["a", "b", "c"]<br>');
        document.write('obj={name:"tony", gender:"male", age:18}<br>');   
        //測試物件的 for in 迴圈
        document.write('for (var attr in obj) : ');
        for (var attr in obj){            //用在物件時, 迭代對象為屬性 (鍵)
          document.write(attr + ":" + obj[attr] + ", ");
          }
        document.write("<br>");
        //測試陣列的 for in 迴圈
        document.write('for (var idx in arr) : ');
        for (var idx in arr){             //用在陣列時, 迭代對象為索引
          document.write(arr[idx] + ", ");
          }
        document.write("<br>");
        //測試字串的 for in 迴圈
        document.write('for (var idx in str) : ');
        for (var idx in str){             //用在字串時, 迭代對象為索引
          document.write(str[idx] + ", ");
          }
        document.write("<br>");
        //測試陣列的 for of 迴圈
        document.write('for (var ele of arr) : ');
        for (var ele of arr){                //用在陣列時,  迭代對象為元素
          document.write(ele + ", ");
          }
        document.write("<br>");
        //測試陣列的 forEach() 方法
        document.write('arr.forEach : ');
        //測試字串的 for of 迴圈
        document.write('for (var ele of str) : ');
        for (var ele of str){                //用在字串時, 迭代對象為元素 (字元)
          document.write(ele + ", ");
          }
        document.write("<br>");
        arr.forEach(function(ele) {     //只能用在陣列, 迭代對象為元素
          document.write(ele + ",");
          });
        document.write("<br>");
        });
    </script>
  </body>
</html>

結果如下 :




for in 迴圈不僅可用在陣列, 也可以用在物件. 對於陣列而言, for (var idx in arr) 中迭代的對象是索引 idx, 故取得陣列元素要用 arr[idx]. 但對於物件而言, for (var attr in obj) 中迭代的是物件的鍵 (屬性), 但其值仍要用 obj[attr] 存取, 用 obj.attr 會得到 undefined. 與 for in 不同的是, for (var ele of arr) 只能用在字串或陣列的迭代, 不可用在物件, 且迭代的對象是字串之字元或陣列之元素而非索引, 這是 for in 與 for of 最大的不同. forEach() 方法與 for of 迴圈很相似, 都只能用在陣列, 且迭代的對象都是元素, 參考 :

JavaScript中for of和for in的差別

jQuery 的 $.each() 函數可同時迭代陣列與物件 (但不能迭代字串), 其介面如下 :

$.each(array/object, function(key/index, value))

第一參數為要迭代的對象, 可以傳入陣列或物件. 第二參數為回呼函數, 其傳入參數有兩個, 第一個是陣列的索引或物件的屬性, 第二個是值.


範例 2 : $.each() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr=["a", "b", "c"];
        var obj={name:"tony", gender:"male", age:18};
        document.write('arr=["a", "b", "c"]<br>');
        document.write('obj={name:"tony", gender:"male", age:18}<br>');   
        document.write('str="Hello World!"<br>');
        //測試陣列的 $.each() 迴圈
        document.write('$.each(arr, callback) : ');
        $.each(arr, function(idx, value){
          document.write("arr[" + idx + "]=" + value + ", ");
          });
        document.write("<br>");
        //測試物件的 $.each() 迴圈
        document.write('$.each(obj, callback) : ');
        $.each(obj, function(key, value){
          document.write("obj." + key + "=" + value + ", ");
          });
        document.write("<br>");
        //測試物件的 $.each() 迴圈
        document.write('$.each(document.location, callback) : ');
        $.each(document.location, function(key, value){
          document.write("document.location." + key + "=" + value + ", ");
          });
        document.write("<br>");
        });
    </script>
  </body>
</html>

此例分別迭代拜訪了陣列元素與物件成員, 注意傳入回呼函數的第一參數在陣列為其索引, 在物件為其屬性. 結果如下 :

arr=["a", "b", "c"]
obj={name:"tony", gender:"male", age:18}
str="Hello World!"
$.each(arr, callback) : arr[0]=a, arr[1]=b, arr[2]=c,
$.each(obj, callback) : obj.name=tony, obj.gender=male, obj.age=18,
$.each(document.location, callback) : document.location.href=http://tony1966.xyz/test/jquerytest/jquerytest_utilities_each.htm, document.location.ancestorOrigins=[object DOMStringList], document.location.origin=http://tony1966.xyz, document.location.protocol=http:, document.location.host=tony1966.xyz, document.location.hostname=tony1966.xyz, document.location.port=, document.location.pathname=/test/jquerytest/jquerytest_utilities_each.htm, document.location.search=, document.location.hash=, document.location.assign=function assign() { [native code] }, document.location.reload=function reload() { [native code] }, document.location.toString=function toString() { [native code] }, document.location.replace=function replace() { [native code] },

注意, $.each() 不能用來迭代字串, 要用 for in 或 for of 迴圈才可以.


2. $.grep() 函數 :

此函數用來過濾陣列元素, 陣列元素會逐一迭代傳入回呼函數中, 回呼函數中的條件式若傳回 true 則此元素會被傳回給新陣列, 否則會被丟棄, 傳回值為過濾後之新陣列, 其介面如下 :

$.grep(array, function(value [, index]) [, invert])

第一個參數為欲過濾的陣列, 第二個參數為回呼函數, 可傳入兩個參數, 第一個是必要的被迭代之陣列元素 value, 第二個是備選的索引 index. $.each() 的第三個參數為備選之布林值, 預設為 false, 若設為 true, 則過濾規則會相反, 即符合條件的被丟棄, 不符條件的被傳回給新陣列.


範例 3 : $.grep() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr=[34,78,99,84,56,22,100];
        document.write('arr=[34,78,99,84,56,22,100]<br>');
        var narr=$.grep(arr, function(value){   //過濾元素值
          return value >= 60;
          });
        document.write("value >= 60 : " + narr.join() + "<br>");
        narr=$.grep(arr, function(value){    //反向過濾
          return value >= 60;
          }, true);
        document.write("value >= 60 (invert) : " + narr.join() + "<br>");
        narr=$.grep(arr, function(value, index){    //過濾索引
          return index > 4;
          });
        document.write("index > 4 : " + narr.join() + "<br>");
        });
    </script>
  </body>
</html>

此例使用 $.grep() 對同一個成績陣列過濾, 但條件不同, 第一個過濾分數大於等於 60 分者; 第二個則是使用 invert 參數進行反向過濾 (低於 60 分者), 第三個是過濾陣列索引.

執行結果如下 :

arr=[34,78,99,84,56,22,100]
value >= 60 : 78,99,84,100
value >= 60 (invert) : 34,56,22
index > 4 : 22,100

對於較複雜的過濾條件可在比對條件中使用正規表達式, 例如美國的郵遞區號 (ZIP) 格式為 10 個字元, 前面五個數字後面四個數字中間用 dash 串接, 例如 22162-1010, 其正規表達式為 /^\d{5}(-\d{4})?$/, 若要從一堆 ZIP 號碼中挑出正確的號碼可用字串的 match() 方法 :

return value.match(/^\d{5}(-\d{4})?$/) != null


範例 3 : $.grep() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr=["12345-6789","234567-123","8888a-5432"];
        document.write('arr=["12345-6789","234567-123","8888a-5432"]<br>');
        var narr=$.grep(arr, function(value){
          return value.match(/^\d{5}(-\d{4})?$/) != null;
          });
        document.write("valid ZIP: " + narr.join() + "<br>");
        var narr=$.grep(arr, function(value){
          return value.match(/^\d{5}(-\d{4})?$/) != null;
          }, true);
        document.write("invalid ZIP: " + narr.join() + "<br>");
        });
    </script>
  </body>
</html>

結果如下 :

arr=["12345-6789","234567-123","8888a-5432"]
valid ZIP: 12345-6789
invalid ZIP: 234567-123,8888a-5432


3. $.map() 函數 :

此函數用來將陣列或物件透過迭代運算轉換 (映射) 成另一個陣列, 其介面如下 :

$.map(array/object, function(value [, index/attr])

第一個參數為待轉換之陣列或物件, 第二個參數為回呼函數, 它也可傳入兩個參數, 第一個是陣列元素或物件之值 (必要), 第二個是可有可無的陣列索引或物件的屬性, 回呼函數的傳回值會被收集起來成為轉換後的新陣列, 但有一些特殊的回傳值要注意 :
  • 如果傳回 null 或 undefined 就不會被收集, 這樣轉換後的新陣列或物件就會比原來的小 (失去對映).
  • 如果回傳值不是純量 (scaler), 而是向量 (即一個陣列), 則這些向量會全部串接成一個陣列. 
例如 :


範例 4 : $.map(陣列) 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var score=[34,78,99,84,56,22,100];
        document.write('arr=[34,78,99,84,56,22,100]<br>');
        //傳回全部且不及格加 5 分
        var result1=$.map(score, function(value){
          return value < 60 ? value + 5 : value;
          });
        document.write("result1[]: " + result1.join() + "<br>");
        //只傳回及格者並加 5 分
        var result2=$.map(score, function(value){
          return value > 60 ? value + 5 : null;      //null 濾掉不及格者
          });
        document.write("result2[]: " + result2.join() + "<br>");
        //傳回陣列元素與索引
        var result3=$.map(score, function(value, index){
          return value > 60 ? [value, index] : null;
          });
        document.write("result3[]: " + result3.join() + "<br>");
        //轉換字串陣列
        var data=["2","4.5","23%","10","@!","22"];
        document.write('data=["2","4.5","23%","10","@!","22"]<br>');
        var result4=$.map(data, function(value){
          var num=new Number(value);
          return isNaN(num) ? undefined : num;     //undefined 濾掉非數字
          });
        document.write("result4[]: " + result4.join() + "<br>");
        });
    </script>
  </body>
</html>

此例成績陣列 score 利用回呼函數進行轉換, 只要沒有傳回 null 或 undefined則新舊陣列長度一樣, 否則轉換後新陣列較小. 陣列 data 用來示範如何濾掉非數字元素, 結果如下 :

arr=[34,78,99,84,56,22,100]
result1[]: 39,78,99,84,61,27,100
result2[]: 83,104,89,105
result3[]: 78,1,99,2,84,3,100,6
data=["2","4.5","23%","10","@!","22"]
result4[]: 2,4.5,10,22

$.map() 也可以傳入物件進行轉換, 但傳回值為一陣列, 例如 :


範例 5 : $.map(物件) 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var obj1={math:57,chinese:95,english:78,art:45};
        document.write('obj1={math:57,chinese:95,english:78,art:45}<br>');
        var result1=$.map(obj1, function(value, attr){
          return value < 60 ? attr : null;    //傳回及格科目
          });
        document.write("value < 60 : " + result1 + "<br>");
        document.write($.isArray(result1) + "<br>");
        var obj2={a:1,b:[2,3],c:{c1:4,c3:5}};
        document.write('obj2={a:1,b:[2,3],c:{c1:4,c3:5}}<br>');
        var result2=$.map(obj2, function(value, attr){
          return value;   //直接傳回屬性值
          });
        document.write("value : " + result2 + "<br>");
        document.write($.isArray(result2) + "<br>");
        });
    </script>
  </body>
</html>

此例傳入 $.map() 的是兩個物件, obj1 為成績單, 回呼函數判斷屬性值 (成績) 是否及格, 是傳回科目 attr (屬性), 否則傳回 null (不收集), 因此 $.map() 收集到的轉換後之陣列為及格科目所組成之陣列. obj2 是較複雜的物件, 屬性 b 之值為陣列, 傳回時會與其他元素串接, 屬性 c 為一物件, $.map() 只會迭代第一層屬性, 不會往下迭代, 因此傳回 [Object Object], 結果如下 :

obj1={math:57,chinese:95,english:78,art:45}
value < 60 : math,art
true
obj2={a:1,b:[2,3],c:{c1:4,c3:5}}
value : 1,2,3,[object Object]
$.isArray(result2): true
$.isArray(result2[3]): false
$.isPlainObject(result2[3]): true

此處使用了 $.isArray() 與 $.isPlainObject() 來檢驗回呼函數傳回值, 可見屬性 c 之值為物件被直接傳回去, 因此 result2 陣列的索引 3 為一個物件.


4. $.makeArray() 函數 :

Javascript 或 jQuery 許多函數或物件方法 (例如工廠函數 $) 的傳回值是類陣列物件 (例如函數引數 arguments), 並非原生陣列, 因此無法使用陣列的 push(), pop(), 或 reverse() 等方法. $.makeArray() 函數可用來將這些陣列式物件轉換成真正的 Javascript 陣列, 其介面如下 :

$.makeArray(object)

傳入參數只有一個, 即要轉換的物件, 傳回值為一個原生單純的 Javascript 陣列. 例如 :


範例 6 : $.makeArray() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var obj={a:1, b:2, c:3};
        document.write('obj={a:1, b:2, c:3}<br>');
        document.write('arr=$.makeArray(obj)<br>');
        var arr=$.makeArray(obj);
        document.write("$.isArray(arr): " + $.isArray(arr) + "<br>");
        document.write("arr.length : " + arr.length + "<br>");
        document.write('$.each(arr, callback) : ');
        $.each(arr, function(idx, value){
          document.write("arr[" + idx + "]=" + value + ", ");
          });
        document.write("arr[]: " + arr.join() + "<br>");
        document.write("$.isPlainObject(arr[0]): " + $.isPlainObject(arr[0]) + "<br>");
        document.write("for (var attr in arr[0]): ");
        for (var attr in arr[0]){       
          document.write(attr + ":" + arr[0][attr] + ", ");
          }
        });
    </script>
  </body>
</html>

結果如下 :

obj={a:1, b:2, c:3}
arr=$.makeArray(obj)
$.isArray(arr): true 
arr.length : 1 
$.each(arr, callback) : arr[0]=[object Object], arr[]: [object Object]
$.isPlainObject(arr[0]): true
for (var attr in arr[0]): a:1, b:2, c:3

此例用 $.makeArray() 將一個簡單的物件 obj={a:1, b:2, c:3} 轉成陣列, 可見其作法是將物件內容打包為一個陣列元素 (用 $.isArray 檢查為 true), 所以轉換後得到的 arr 陣列只有一個元素, 其值用 $.isPlainObject() 去檢查可知為一物件.

下面範例則是用 $.makeArray() 將 DOM 元素的 jQuery 物件轉成陣列, 這樣就可以呼叫陣列的 push(), pop(), reverse() 等方法操作元素 :


範例 7 : $.makeArray() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <ul id="result">
      <li>a</li>
      <li>b</li>
      <li>c</li>
      <li>d</li>
      <li>e</li>
    </ul>
    <button id="reverse">reverse</button>
    <button id="push">push</button>
    <button id="pop">pop</button>
    <button id="sort">sort</button><br><br>
    <div id="info"></div>
    <script>
      $(function(){
        var i=1;
        $("#reverse").click(function(){
          var obj=$("li");
          var arr=$.makeArray(obj);
          arr.reverse();           //陣列反轉
          var info=[];
          info.push('obj=$("li")<br>');
          info.push('arr=$.makeArray(obj)<br>');
          info.push("$.isArray(arr): " + $.isArray(arr) + "<br>");
          info.push("arr.length : " + arr.length + "<br>");
          $("#info").html(info.join(""));
          $("#result").html($(arr));
          });
        $("#push").click(function(){
          $("#result").append("<li>" + (i++) + "</li>");
          var obj=$("li");
          var arr=$.makeArray(obj);
          var info=[];
          info.push('obj=$("li")<br>');
          info.push('arr=$.makeArray(obj)<br>');
          info.push("$.isArray(arr): " + $.isArray(arr) + "<br>");
          info.push("arr.length : " + arr.length + "<br>");
          $("#info").html(info.join(""));
          $("#result").html($(arr));
          });
        $("#pop").click(function(){
          var obj=$("li");
          var arr=$.makeArray(obj);
          arr.pop();      //刪除陣列最後一個元素
          var info=[];
          info.push('obj=$("li")<br>');
          info.push('arr=$.makeArray(obj)<br>');
          info.push("$.isArray(arr): " + $.isArray(arr) + "<br>");
          info.push("arr.length : " + arr.length + "<br>");
          $("#info").html(info.join(""));
          $("#result").html($(arr));
          });
        $("#sort").click(function(){
          var obj=$("li");
          var arr=$.makeArray(obj);
          arr.sort();
          var info=[];
          info.push('obj=$("li")<br>');
          info.push('arr=$.makeArray(obj)<br>');
          info.push("$.isArray(arr): " + $.isArray(arr) + "<br>");
          info.push("arr.length : " + arr.length + "<br>");
          $("#info").html(info.join(""));
          $("#result").html($(arr));
          });
        });
    </script>
  </body>
</html>

此例中網頁預設已有 a, b, c 清單, 按 reverse 按鈕會先用選擇器取得全部 li 元素物件, 透過 $.makeArray() 將此物件集合轉成陣列後, 呼叫陣列的 reverse() 方法讓清單元素反轉順序, 再將結果用 $() 工廠函數轉回 DOM 之jQuery 物件覆蓋原來的清單更新網頁. 同理, 按 pop 會從 arr 陣列中去除最後一個元素. 但 push 部分若用 arr.push("<li></li>") 會出現錯誤, 故暫時用 append() 先新增清單, 還沒用到 push() 函數. 結果如下 :




但 sort() 似乎無效, 這可能是其元素為物件之故.


5. $.merge() 函數 :

此函數用來合併兩個陣列, 其介面如下 :

$.merge(array1, array2)

此函數有兩個必要參數, 即要合併的陣列, 合併是將第二個陣列合併到第一個陣列, 然後將第一個陣列傳回. 此合併操作 array1 會改變, 但 array2 則不變, 例如 :


範例 8 : $.merge() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr1=[1,2,3];
        var arr2=[4,5,6];
        document.write('arr1=[1,2,3]<br>');
        document.write('arr2=[4,5,6]<br>');
        var arr1_bak=$.merge([], arr1);     //備份 arr1
        document.write('arr1_bak[]: ');
        $.each(arr1_bak, function(value){
          document.write(value + ", ");
          });
        document.write("<br>");
        var arr3=$.merge(arr1, arr2);   //將 arr2 合併到 arr1 並傳回給 arr3
        document.write('arr3[]: ');
        $.each(arr3, function(value){
          document.write(value + ", ");
          });
        document.write("<br>");
        document.write('arr1[]: ');
        $.each(arr1, function(value){   //檢查 arr1 內容
          document.write(value + ", ");
          });
        document.write("<br>");
        });
    </script>
  </body>
</html>

由於第一個陣列為結果陣列會被改變, 因此如果有保留需要可先用空陣列 [] 與 arr1 先合併, 將 arr1 備份到 arr1_bak, 結果如下 :

arr1=[1,2,3]
arr2=[4,5,6]
arr1_bak[]: 0, 1, 2,
arr3[]: 0, 1, 2, 3, 4, 5,
arr1[]: 0, 1, 2, 3, 4, 5,

可見合併後 arr1 與 arr3 是一樣的. 事實上可以將複製陣列結果當作 $.merge() 的第一參數, 例如 :

var arr3=$.merge($.merge([], arr1), arr2);

這樣就不需要用到 arr1_bak 了, 而且 arr1 與 arr2 都不變.


6. $.unique() 函數 :

此函數用來剔除 DOM 元素陣列中的重複元素, 其介面如下 :

$.unique(array)

傳回值為剔除重複 DOM 元素經排序過的陣列. 注意, 此函數只能用於 DOM元素陣列, 不能用在一般陣列, 否則會出現非預期結果, 此函數在 jQuery 3 已經被棄用, 改為 $.uniqueSort(), 但 $.unique() 仍作為其別名而可繼續使用.


範例 9 : $.unique(一般陣列) 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <script>
      $(function(){
        var arr=[9,3,4,3,7,3];
        document.write('arr=[9,3,4,3,7,3]<br>');
        var arr1=$.unique(arr);
        document.write('arr1[]: ');
        $.each(arr1, function(index, value){
          document.write(value + ", ");
          });
        });
    </script>
  </body>
</html>

結果如下 :

arr=[9,3,4,3,7,3]
arr1[]: 9, 3, 4, 3, 7, 3,

可見 $.unique() 對一般陣列無效, 必須傳入 DOM 元素陣列, 例如 :


範例 10 : $.unique(DOM 元素陣列) 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <div class="red">a</div>
    <div class="blue">b</div>
    <div class="blue">c</div>
    <div class="green">d</div>
    <div class="red">e</div>
    <p id="result"></p>
    <script>
      $(function(){
        var arr=[];
        //取得 div 元素陣列 div0
        var div0=$("div").get();
        arr.push('div0=$("div").get() : ');
        $.each(div0, function(k, v){
          arr.push($(v).html() + ',');
          });
        arr.push('<br>');
        //取得 class=blue 之元素陣列 div1
        var div1=$(".blue").get();
        arr.push('div1=$(".blue").get() : ');
        $.each(div1, function(k, v){
          arr.push($(v).html() + ',');
          });
        arr.push('<br>');
        //串接元素陣列 div0 與 div1 傳回 div2
        var div2=div0.concat(div1);
        arr.push('div2=div0.concat(div1) : ');
        $.each(div2, function(k, v){
          arr.push($(v).html() + ',');
          });
        arr.push('<br>');
        //去除 div2 中的重複元素傳回 div3
        var div3=$.unique(div2);
        arr.push('div3=$.unique(div2) : ');
        $.each(div3, function(k, v){
          arr.push($(v).html() + ',');
          });
        $("#result").html(arr.join(""));
        });
    </script>
  </body>
</html>

結果如下 :

a
b
c
d
e
div0=$("div").get() : a,b,c,d,e,
div1=$(".blue").get() : b,c,
div2=div0.concat(div1) : a,b,c,d,e,b,c,
div3=$.unique(div2) : a,b,c,d,e,

可見串接後重複的 class=blue 元素 b,c 被 unique() 刪除了.


7. $.inArray() 函數 :

此函數用來陣列中是否含有特定元素, 其介面如下 :

$.inArray(value, array [, fromIndex])

第一個參數為要在陣列中搜尋之值, 第二個參數是要搜尋之陣列, 第三個參數是要搜尋之索引起點, 預設為 0 (即從頭開始搜尋). 此函數會傳回搜尋到的第一個元素索引, 若未找到則傳回 -1, 這與 Javascript 搜尋子字串的 indexOf() 方法功能類似, 例如 :


範例 11 : $.inArray() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <div id="result"></div>
    <script>
      $(function(){
        var arr=[];
        var fruits=["apple", "grape", "guava"];
        arr.push('var arr=["apple", "grape", "guava"]');
        var idx=$.inArray("grape", fruits);
        arr.push('$.inArray("grape", fruits): ' + idx);
        var idx=$.inArray("pineapple", fruits);
        arr.push('$.inArray("pineapple", fruits): ' + idx);
        var idx=$.inArray("guava", fruits);
        arr.push('$.inArray("guava", fruits): ' + idx);
        $("#result").html(arr.join("<br>"));
        });
    </script>
  </body>
</html>

結果如下 :




8. $.isArray() 函數 :

此函數用來檢測傳入參數是否為陣列, 只有用 [] 或 new Array() 建立的陣列才會傳回 true, 其介面如下 :

$.isArray(param)


範例 12 : $.isArray() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <div id="result"></div>
    <script>
      $(function(){
        var arr=[];
        var b=$.isArray([]);
        arr.push('$.isArray([]): ' + b);
        b=$.isArray(new Array("a", "b"));
        arr.push('$.isArray(new Array("a", "b")): ' + b);
        b=$.isArray({});
        arr.push('$.isArray({}): ' + b);
        b=$.isArray($);
        arr.push('$.isArray($): ' + b);
        b=$.isArray("Hello World!");
        arr.push('$.isArray("Hello World!"): ' + b);
        $("#result").html(arr.join("<br>"));
        });
    </script>
  </body>
</html>

結果如下 :




9. $.isPlainObject() 函數 :

此函數用來檢測傳入參數是否為普通物件, 即用 {} 或 new Object() 所建立之物件, 其介面如下 :

$.isPlainObject(param)

參數可以是任何型態資料 (例如 $ 或 jQuery 物件), 但只有傳入普通物件時才會傳回 true, 例如 :


範例 13 : $.isPlainObject() 測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <div id="result"></div>
    <script>
      $(function(){
        var arr=[];
        var b=$.isPlainObject({});
        arr.push('$.isPlainObject({}): ' + b);
        b=$.isPlainObject(new Object());
        arr.push('$.isPlainObject(new Object()): ' + b);
        b=$.isPlainObject("Hello World!");
        arr.push('$.isPlainObject("Hello World!"): ' + b);
        b=$.isPlainObject(document.location);
        arr.push('$.isPlainObject(document.location): ' + b);
        $("#result").html(arr.join("<br>"));
        });
    </script>
  </body>
</html>

結果如下 :




此例主要在測試 $.isPlainObject() 函數只有用 {} 與 new Object() 建立的普通物件才會傳回 true, 否則傳回 false.


二. 字串處理 :

jQuery 的字串工具函數有如下四個 :


 jQuery 字串工具函數 說明
 $.trim(string) 去除傳入字串前後的空白字元, 傳回結果字串, 原字串不變
 $.parseHTML(string) 剖析 JSON 格式字串, 傳回 Javascript 物件
 $.parseXML(string) 剖析 XML 格式字串, 傳回 XML 文件
 $.parseJSON(string) 剖析 JSON 格式字串, 傳回 Javascript 物件 


這些函數主要用來彌補 Javascript 內建的字串函數之不足. 其中 $.parseJSON() 在 jQuery 3.0 已被廢止, 剖析 JSON 可用 Javascript 的 JSON.parse().


1. $.trim() 函數 :

許多語言例如 PHP 或 Python 內建的字串處理函數都有刪除前後空白字元的功能, 但 Javascript 卻沒有, jQuery 的 $.trim() 彌補了這個缺憾. 此函數常用於前端表單驗證, 用來去除文字欄位輸入字串頭尾的空白字元 (white space), 包括空格, 換行, Tab 等字元 (即正規表示法中的 /s 字元), 避免傳送至後端時出現錯誤 (例如帳密多了一個空白導致登入失敗).

$.trim() 只有一個參數, 即要進行修剪的字串 :

$.trim(str)

它會傳回修剪後的字串, 原字串內容不變, 例如 :


範例 14 : $.trim() 函數測試 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <input type="text" id="origin">
    <button id="btn">$.trim()</button>
    <input type="text" id="trimed">
    <div id="len"></div>
  <script> 
    $(function(){
      $("#btn").click(function(){
        var origin=$("#origin").val();
        var trimed=$.trim(origin);
        $("#trimed").val(trimed);
        var out="輸入長度:" + origin.length + " 輸出長度:" + trimed.length;
        $("#len").html(out);
        });
      });
  </script>
  </body>
</html>

此例有兩個文字欄位, 左邊輸入頭尾有空格的字串後, 按 $.trim() 鈕會將頭尾空格去除後顯示在右方文字欄位中, 並於下方顯示各自長度, 結果如下 :




可見頭尾空白被去除後, 字串長度變短了.


2. $.parseHTML() 函數

此函數用來剖析 HTML 字串, 結果傳回 DOM 元素節點陣列, 其介面為 :

$.parseHTML(htmlString [, context] [, keepScripts])

第一參數 htmlString 為待剖析之 HTML 字串, 第二參數 context (備選) 用來指定要在網頁中何處建立元素, 預設是在 document 元素上, 第二參數 keepScripts 為布林值, 設定是否要保持其中的指令碼, 為了安全預設為 false.


範例 15 : $.parseHTML() 函數測 (不含 script) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <p id="result"></p>
    <script>
      $(function(){
        var arr=[];
        var str="Hello, <b><u>W</u>orld</b>";
        var html=$.parseHTML(str);
        arr.push('str="Hello, <b><u>W</u>orld</b>');
        $.each(html, function(i, v){
          arr.push('<li>' + v.nodeName + '</li>');
          });
        $("#result").html("<ul>" + arr.join("") + "</ul>");
        });
    </script>
  </body>
</html>

此例用 $.parseHTML() 剖析了一個簡單的 HTML 字串 "Hello, <b><u>W</u>orld</b>", 其傳回值為 HTML 的 DOM 元素物件陣列, 每一個元素代表一個 DOM 節點, 然後用 $.each() 來迭代遍歷此物件陣列, 於迴圈中顯示節點名稱 (nodeName 屬性), 為了顯示剖析結果, 使用一個空陣列 arr 來儲存每一個節點 (使用 li 清單), 最後用 join() 串接頭尾加上 ul 清單元素, 結果如下 :




可見 $.parseHTML() 只剖析了第一層元素而已, 它不會自動往下剖析, 所以只看到 text 與 b 元素, 而看不到 u 元素.

如果 HTML 字串中包含了 Javascript 程式碼, 則 $.parseHTML() 因安全考量預設不會對 script 元素進行解析, 若要剖析可將 keepScripts 參數設為 true, 如下面範例所示 :


範例 16 : $.parseHTML() 函數測試 (含 script) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    <p id="result"></p>
    <script>
      $(function(){
        var arr=[];
        var str="<b>Hello, World</b><script>alert('ok');<\/script>";
        var html=$.parseHTML(str, document, true);
        arr.push("<b>Hello, World</b><script>alert('ok');<\/script><br>");
        $.each(html, function(i, v){
          arr.push('<li>' + v.nodeName + '</li>');
          });
        $("#result").html("<ul>" + arr.join("") + "</ul>");
        });
    </script>
  </body>
</html>

此例將 $.parseHTML() 的備選第三參數設為 true 即啟動對 script 元素之剖析 (第二參數用預設 document), 結果如下 :




可見解析出 script 元素節點了. 參考:

jQuery.parseHTML() 函式詳解


3. $.parseXML() 函數 : 

此函數用來剖析 XML 字串, 其介面如下 :

$.parseXML(xmlString)

傳入參數為一個 XML 格式字串, 傳回值為一 XML 文件物件.


範例 17 : $.parseXML() 函數測試 [看原始碼]


"<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta class="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <style>
    </style>
  </head>
  <body>
    str="<?xml version='1.0' ?><result><user>tony</user><pwd>123</pwd></result>";
    <p id="result"></p>
    <script>
      $(function(){
        var arr=[];
        var str="<?xml version='1.0' ?><result><user>tony</user><pwd>123</pwd></result>";
        var xmldoc=$.parseXML(str);
        var xml=$(xmldoc);                //將 XML 文件物件轉成 jQuery 物件
        var user=xml.find("user");     //取得 XML 節點物件
        var pwd=xml.find("pwd");     //取得 XML 節點物件
        arr.push("user=" + user.text());      //取得 XML 節點文字內容
        arr.push("pwd=" + pwd.text());     //取得 XML 節點文字內容
        $("#result").html(arr.join("<br>"));
        });
    </script>
  </body>
</html>"

此例使用 $.parseXML() 剖析一個簡單的 XML 字串, 然後用 $() 工廠函數將傳回的 XML 文件物件轉成 jQuery 物件, 以便利用 jQuery 的 find() 方法來找尋 XML 節點物件, 找到後再呼叫 XML 節點物件的 text() 方法取出其節點內容, 結果如下 :




$.parseXML() 只是剖析字串後加上一堆 XML 文件的屬性與方法而已, 其實直接將上例中的 str 傳給工廠函數 $() 也可以得到同樣結果, 如果只是要取得 XML 字串中特定節點之內容並不需要經過 $.parseXML() 剖析, 直接轉成 jQuery 物件即可, 例如用 Ajax 取得遠端 XML 資料時即是如此, 參考 :

測試 jQuery 的 Ajax 函數 $.ajax()

與 Ajax 操作相關的工具函數除了上面這篇所測試的 $.ajax() 外, 還有 $.get(), $.post, $.getJSON(), $.getScript(), 以及 $.serialize() 與 $.params() 等函數, 參考 :

# jQuery 的高階 Ajax 函數測試

沒有留言:

張貼留言