掌握JavaScript
基礎知識,可以使用JavaScript
編寫一些複雜度不大的交互功能。javascript
javascript
是什麼javascript
代碼<script src ="">
引入<script></script>
<script></script>
位置<script></script>
標籤儘量放到''標籤的底部,以儘可能減小對整個頁面下載的影響。<script></script>
標籤,就能夠減小性能消耗。文件合併的工做可經過離線的打包工具或者一些實時的在線服務來實現。<html> <head> <title>Script Defer Example</title> </head> <body> <script type="text/javascript" defer> alert("defer"); </script> <script type="text/javascript"> alert("script"); </script> <script type="text/javascript"> window.onload = function(){ alert("load"); }; </script> </body> </html>
這段代碼在頁面處理過程當中彈出三次對話框。不支持 defer 屬性的瀏覽器的彈出順序是:「defer」、「script」、「load」。而在支持 defer 屬性的瀏覽器上,彈出的順序則是:「script」、「defer」、「load」。請注意,帶有 defer 屬性的script元素不是跟在第二個後面執行,而是在 onload 事件被觸發前被調用。
aysnc:可以異步地加載和執行腳本,不由於加載腳本而阻塞頁面的加載。可是有一點須要注意,在有 async 的狀況下,JavaScript 腳本一旦下載好了就會執行,因此頗有可能不是按照本來的順序來執行的。若是 JavaScript 腳本先後有依賴性,使用 async 就頗有可能出現錯誤。
動態腳本加載:php
function loadScript(url, callback){ var script = document.createElement ("script") script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
loadScript("script1.js", function(){ alert("File is loaded!"); });
JavaScript
是一種弱類型或者說動態語言。這意味着你不用提早聲明變量的類型,在程序運行過程當中,類型會被自動肯定。這也意味着你可使用同一個變量保存不一樣類型的數據:var foo = 42; // foo is a Number now var foo = "bar"; // foo is a String now var foo = true; // foo is a Boolean now
特別的html
// 判斷數組 function isArray(arr) { return Array.isArray(arr); } // 判斷函數 function isFunction(fn) { return Object.prototype.toString.call(fn) === '[object Function]'; }
值類型
聲明一個值類型變量,編譯器會在棧上分配一個空間,這個空間對應着該值類型變量,空間裏存儲的就是該變量的值。存儲在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置。java
引用類型
引用類型的實例分配在堆上,新建一個引用類型實例,獲得的變量值對應的是該實例的內存分配地址,這就像您的銀行帳號同樣。存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存處。
爲變量賦值時,ECMAScript 的解釋程序必須判斷該值是原始類型,仍是引用類型。要實現這一點,解釋程序則需嘗試判斷該值是否爲 ECMAScript 的原始類型之一,即 Undefined、Null、Boolean、Number 和 String 型。因爲這些原始類型佔據的空間是固定的,因此可將他們存儲在較小的內存區域 - 棧中。這樣存儲便於迅速查尋變量的值。
在許多語言中,字符串都被看做引用類型,而非原始類型,由於字符串的長度是可變的。ECMAScript 打破了這一傳統。
若是一個值是引用類型的,那麼它的存儲空間將從堆中分配。因爲引用值的大小會改變,因此不能把它放在棧中,不然會下降變量查尋的速度。相反,放在變量的棧空間中的值是該對象存儲在堆中的地址。地址的大小是固定的,因此把它存儲在棧中對變量性能無任何負面影響。以下圖所示:c++
JavaScript中原始值包括:undefined,null,布爾值,數字和字符串。
引用類型主要指對象(包括數組和函數)。web
原始值是不可更改的。對象的值是可修改的。
原始值的比較是值的比較。對象的比較並不是值的比較。對象的值都是引用,對象的比較均是引用的比較,當且僅當他們都引用同一個基對象時,他們才相等。
參考:ajax
ECMAScript 原始值和引用值
對象的讀取、遍歷方式
參考:JavaScript 指南-使用對象正則表達式
對象
在javascript中,一個對象能夠是一個單獨的擁有屬性和類型的實體。咱們拿它和一個杯子作下類比。一個杯子是一個對象(物體),擁有屬性。杯子有顏色,圖案,重量,由什麼材質構成等等。一樣,javascript對象也有屬性來定義它的特徵。數據庫
屬性
一個 javascript 對象有不少屬性。一個對象的屬性能夠被解釋成一個附加到對象上的變量。對象的屬性和普通的 javascript 變量基本沒什麼區別,僅僅是屬性屬於某個對象。屬性定義了對象的特徵(譯註:動態語言面向對象的鴨子類型)。你能夠經過點符號來訪問一個對象的屬性。JavaScript 對象的屬性也能夠經過方括號訪問。編程
枚舉
你能夠在 for...in 語句中使用方括號標記以枚舉一個對象的全部屬性。爲了展現它如何工做,下面的函數當你將對象及其名稱做爲參數傳入時,顯示對象的屬性:
function showProps(obj, objName) { var result = ""; for (var i in obj) { if (obj.hasOwnProperty(i)) { result += objName + "." + i + " = " + obj[i] + "\n"; } } return result; } var srcObj = { a: 1, b: { b1: ["hello", "hi"], b2: "JavaScript" } }; console.log(showProps(srcObj,'srcObj')); console: srcObj.a = 2 srcObj.b = [object Object]
這裏使用 hasOwnProperty() 是爲了確保是本身的屬性而非繼承的屬性。
能夠以下寫,跳過這個對象的方法:
function showPropsWithoutFun(obj, objName) { var result = ""; for (var i in obj) { if (!obj.hasOwnProperty(i)) { //跳過繼承屬性 continue; } if (typeof obj[i] === "function") { //跳過這個對象的方法 continue; } result += objName + "." + i + "=" + obj[i] + "\n"; } return result; }
相關的方法還有:Object.keys(), Object.getOwnPropertyNames()
Object.keys() 方法會返回一個由給定對象的全部可枚舉自身屬性的屬性名組成的數組,數組中屬性名的排列順序和使用for-in循環遍歷該對象時返回的順序一致(二者的主要區別是 for-in 還會遍歷出一個對象從其原型鏈上繼承到的可枚舉屬性)。
Object.getOwnPropertyNames() 方法返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性)組成的數組。
Object.create() 方法建立一個擁有指定原型和若干個指定屬性的對象。
定義方法
一個方法 是關聯到某個對象的函數,或者簡單地說,一個方法是一個值爲某個函數的對象屬性。定義方法就象定義普通的函數,除了它們必須被賦給對象的某個屬性。例如:
objectName.methodname = function_name; var myObj = { myMethod: function(params) { // ...do something } };
// 使用遞歸來實現一個深度克隆,能夠複製一個目標對象,返回一個完整拷貝 // 被複制的對象類型會被限制爲數字、字符串、布爾、日期、數組、Object對象。不會包含函數、正則對象等 function cloneObject(src) { var o; if (Object.prototype.toString.call(src) === "[object Array]") { o = []; } else { o = {}; } for (var i in src) { if (src.hasOwnProperty(i)) { if (typeof src[i] === "object") { o[i] = cloneObject(src[i]); } else { o[i] = src[i]; } } } return o; }
淺度克隆:基本類型爲值傳遞,對象仍爲引用傳遞。
深度克隆:全部元素或屬性均徹底克隆,並於原引用類型徹底獨立,即,在後面修改對象的屬性的時候,原對象不會被修改。
簡單來講,對於淺度克隆,講一個對象經過簡單的傳遞給另外一變量時,實際至關於給該對象增添了一個別名,這兩個名字都是指向同一個對象,當源對象更改時,複製的對象也隨之改變。對於深度克隆,則是新建了一個指針指向另外一個對象,這個對象是源對象的一個副本,但源對象更改時,副本不會隨之改變。
//數組去重 function uniuqArr(arr) { var newArr = []; for (var i in arr) { if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]); } } return newArr; }
//比較笨的方法 function simpleTrimW(str) { var newStr = ""; var pos = str.indexOf(" "); while(pos > -1) { var pos_previous = pos; pos = str.indexOf(" ", pos + 1); if (pos != pos_previous +1 ) { //說明中間隔了非空格字符 break; } } var posTwo = str.lastIndexOf(" "); console.log(posTwo); while(posTwo > -1) { var posTwo_pre = posTwo; posTwo = str.lastIndexOf(" ", posTwo - 1); if (posTwo != posTwo_pre - 1) { break; } } return(str.slice(pos_previous + 1, posTwo_pre)); } var str = " hi ed "; console.log(simpleTrim(str)); //hi ed
//去除全部空格和製表符 function simpleTrim1(str) { var newStr = ""; for (var i = 0; i < str.length; i++) { if (str[i] != " " && str [i] != "\t") { newStr = newStr.concat(str[i]); //中間出現的也會被去除 } } console.log(newStr); } var str = " h i io \t o"; console.log(str); simpleTrim1(str); // hiioo
function simpleTrim(str) { var newStr = ""; for (var i = 0; i < str.length; i++) { if (str.charAt(i) != " " && str.charAt(i) != "\t") { break; } } for (var j = str.length - 1; j >= 0; j--) { if (str.charAt(j) != " " && str.charAt(j) != "\t") { break; } } newStr = str.slice(i, j+1); console.log(newStr); }
一樣是用了兩個循環遍歷,一個從頭開始,一個從尾開始,找到第一個非空格非Tab的字符就跳出遍歷。巧妙在於用了兩個變量i和j來循環,跳出循環時獲得了i和j的值,即字符串中從頭開始和從尾開始的第一個非空格非Tab的字符索引值,從而能夠利用slice方法切割字符串,注意slice中第二個參數要加1。
思路:利用正則匹配開頭和結尾的空白字符,將其替換爲空字符
function trim(str) { return str.replace(/^\s+|\s+$/g, ''); }
function each(arr, fn) { for (var i in arr) { // 遍歷數組 fn(arr[i],i); // 針對數組中每個元素執行fn函數 } } var arr = ['java', 'c', 'php', 'html']; function output(item) { console.log(item) //java c php html } each(arr, output); var arr = ['java', 'c', 'php', 'html']; function output(item, index) { console.log(index + ': ' + item) } each(arr, output);//0: java // 1: c // 2: php // 3: html
也可使用forEach方法
function eachA(arr, fn) { arr.forEach(fn); } //var arr = ['java', 'c++', 'php', 'html']; function output(item, index) { console.log(index + ': ' + item) } //eachA(arr, output); //0: java, 1: c++, 2: php, 3: html
// 獲取一個對象裏面第一層元素的數量,返回一個整數 function getObjectLength(obj) { var n = 0; for (var key in obj) { // console.log(key); //a, b, c n++; } return n; } /* // 使用示例 var obj = { a: 1, b: 2, c: { c1: 3, c2: 4 } }; console.log(getObjectLength(obj)); // 3 */
// 判斷是否爲郵箱地址 function isEmail(emailStr) { // math_phys.d.d@VIP.163.com // 用戶名必須以字母開頭,不能以點結尾 // 考慮域名的級聯 var pattern = /^(\w+\.)*\w+@\w+(\.\w+)+$/; return pattern.test(emailStr); }
// 判斷是否爲手機號 function isMobilePhone(phone) { var pattern = /^(\+\d{1,4})?\d{7,11}$/; return pattern.test(phone); }
// 爲element增長一個樣式名爲newClassName的新樣式 function addClass(element, newClassName) { var oldClassName = element.className; element.className = oldClassName === "" ? newClassName : oldClassName + " " + newClassName; }
首先經過元素的className屬性取出原來的全部類名,注意當有多個類名時,輸出是一個字符串
<div id="div" class="one two three">test</div> <script> div = document.getElementById('div'); console .log(originalClassName = div.className); // one two three </script>
因爲oldclassName是動態可變的,因此要用動態的正則表達式匹配該樣式,\b是匹配單詞邊界,在這裏要使用轉義字符,最後把匹配到的樣式名利用replace方法替換爲空。
// 移除element中的樣式oldClassName function removeClass(element, oldClassName) { var originalClassName = element.className; // 取原來的全部類名 var pattern = new RegExp("\\b" + oldClassName + "\\b"); // 匹配指定類名 element.className = originalClassName.replace(pattern,''); // 移除樣式 }
很簡單,只需判斷父元素是否相同便可。
// 判斷siblingNode和element是否爲同一個父元素下的同一級的元素,返回bool值 function isSiblingNode(element, siblingNode) { return element.parentNode === siblingNode.parentNode; }
Window 尺寸
有三種方法可以肯定瀏覽器窗口的尺寸(瀏覽器的視口,不包括工具欄和滾動條)。
對於Internet Explorer、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight - 瀏覽器窗口的內部高度
window.innerWidth - 瀏覽器窗口的內部寬度
對於 Internet Explorer 八、七、六、5:
document.documentElement.clientHeight
document.documentElement.clientWidth
或者
document.body.clientHeight
document.body.clientWidth
實用的 JavaScript 方案(涵蓋全部瀏覽器):
實例
var w=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
getBoundingClientRect方法返回一個包含left,top,bottom,right四個屬性的對象,能夠獲取元素的相對位置,再加上滾動條的位置,就能獲得元素的絕對位置。
// 獲取element相對於瀏覽器窗口的位置,返回一個對象{x, y} function getPosition(element) { var pos = {}; pos.x = element.getBoundingClientRect(element).left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft); pos.y = element.getBoundingClientRect(element).top + Math.max(document.documentElement.scrollTop, document.body.scrollTop); return pos; }
offsetWidth/offsetHeight: 元素內容 + 內邊距 + 邊框(不包括外邊距、滾動條)
clientWidth/clientHeight: 元素內容 + 內邊距 ;不包括邊框(IE下實際包括)、外邊距、滾動條部分
offsetLeft/offsetTop: 該元素的左上角(邊框外邊緣)與已定位的父容器(offsetParent對象)左上角的距離 ----實際就是外邊距加上父容器內邊距
clientLeft/clientTop: 內邊距的邊緣和邊框的外邊緣之間的水平和垂直距離,也就是邊框寬度
scrollWidth和scrollHeight是元素的內容區域加上內邊距加上溢出尺寸,當內容正好和內容區域匹配沒有溢出時,這些屬性與clientWidth和clientHeight相等
scrollLeft和scrollTop是指元素滾動條位置,它們是可寫的
$
,它和以前的$
是不兼容的,它應該是document.querySelector的功能子集,在不直接使用document.querySelector的狀況下,在你的util.js中完成如下任務:先建一個空列表,用來存放擁有指定樣式名稱的DOM對象,而後取得全部元素(document.getElementsByTagName返回帶有指定標籤名的全部元素,當傳入的標籤名爲*時取所有元素),接着遍歷全部元素,利用getAttribute方法,判斷元素是否有class屬性,若是找到了有class屬性的元素,因爲類不一樣於id,須要考慮一個元素多個類名的狀況,因爲getAttribute方法返回一個字符串,先要將字符串切割成數組,從而能獲得類名個數,而後再遍歷該元素的類名,當有一個元素類名與指定的樣式名同樣時,說明找到了擁有指定className的對象,將其壓入列表,最後獲得了樣式定義包含樣式名的對象列表。在這裏用了兩個for循環,外部的for循環是遍歷全部元素找出有class屬性的元素,內部的for循環是遍歷有class屬性的元素找出有指定class名的元素。
function getClassName(name) { var result = []; var allChildren = null; var currAttr = null; allChildren = document.getElementsByTagName('*'); for (var i = 0; i < allChildren.length; i++) { currAttr =allChildren[i].getAttribute('class'); if (currAttr !== null) { console.log(currAttr); var currAttrsArr = currAttr.split(/\s+/); //類名可能不止一個樣式 console.log(currAttrsArr); for (var j = 0; j < currAttrsArr.length; j++) { if (name === currAttrsArr[j]) { // 無論有多少個類名,只有有一個找到符合的就能夠 result.push(allChildren[i]); } } } } //console.log(result); }
function myQuery(selector, root) { var signal = selector[0]; var allChildren = null; var content = selector.substr(1); // 選擇器名稱 var currAttr = null; // 是否有class屬性的判據 var result = []; // 查找的結果 root = root || document; // 沒有定義父節點,在整個document中查找 switch(signal) { case '#': result.push(document.getElementById(content)); // id只有一個,查找範圍document break; case '.': allChildren = root.getElementsByTagName('*'); // class不僅一個,查找範圍root,取出範圍下全部子元素 for (var i = 0; i < allChildren.length; i++) { // 遍歷全部子元素 currAttr = allChildren[i].getAttribute('class'); // 判斷是否有class屬性,返回屬性值 if (currAttr !== null) { currAttrsArr = currAttr.split(/\s+/); // 將屬性值分割成數組 for(var j = 0; j < currAttrsArr.length; j++) { // 遍歷屬性值 if (content === currAttrsArr[j]) { // 當選擇器名稱與某個屬性值相同時 result.push(allChildren[i]); // 將對應擁有該屬性的元素壓入result } } } } break; case '[': if (content.search('=') === -1) { // 只有屬性沒有值 allChildren = root.getElementsByTagName('*'); for (var i = 0; i < allChildren.length; i++) { if(allChildren[i].getAttribute(selector.slice(1, -1)) !== null) { result.push(allChildren[i]); } } } else { //既有屬性,又有值 allChildren = root.getElementsByTagName("*"); var pattern = /\[(\w+)\s*\=\s*(\w+)\]/; //爲了分離等號先後的內容 var cut = selector.match(pattern); //分離後的結果,爲數組 //alert(cut); //console.log(cut); var key = cut[1]; //鍵 var value = cut[2]; //值 for (i = 0; i < allChildren.length; i++) { if (allChildren[i].getAttribute(key) == value) { result.push(allChildren[i]); } } } break; default: // 開頭不是特殊字符,即查找tagName result = root.getElementsByTagName(selector); break; } return result; }
當全局匹配時,輸出的cut以下:
此時會看到數組cut存放的只是匹配串,因而下面的key和value就爲空,輸出的result就是全部元素了。
// 實現一個簡單的Query function $(selector) { if (!selector) { return null; } if (selector == document) { return document; } selector = selector.trim(); //去除首尾空格 if (selector.indexOf(" ") !== -1) { // 存在空格,即組合查詢 var selectorArr = selector.split(/\s+/); var rootScope = myQuery(selectorArr[0]); // 找出在第一個查詢條件下的全部子節點,做爲第二次查詢的範圍 var i = null; var j = null; var result = []; for (i = 1; i < selectorArr.length; i++) { // i從1開始,rootScope即i=0時 for (j = 0; j < rootScope.length; j++) { result.push(myQuery(selectorArr[i], rootScope[j])); } } return result[0][0]; } else { // 單一查詢 return myQuery(selector,document)[0]; } }
咱們來繼續用封裝本身的小jQuery庫來實現咱們對於JavaScript事件的學習,仍是在你的util.js,實現如下函數:
// 給一個element綁定一個針對event事件的響應,響應函數爲listener function addEvent(element, event, listener) { // your implement } // 例如: function clicklistener(event) { ... } addEvent($("#doma"), "click" , a); // 移除element對象對於event事件發生時執行listener的響應 function removeEvent(element, event, listener) { // your implement }
// 給一個element綁定一個針對event事件的響應,響應函數爲listener function addEvent(element, event, listener) { if (element.addEventListener) { // IE8+ element.addEventListener(event,listener); } else if (element.attachEvent) { // IE8如下 element.attachEvent("on" + event, listener); } else { element["on" + event] = listener; // dom0級 } } // 例如: //function clicklistener(event) { // ... //} addEvent($("#doma"), "click", a); // 移除element對象對於event事件發生時執行listener的響應 function removeEvent(element, event, listener) { if (element.removeEventListener) { element.removeEventListener(event,listener); } else if (element.detachEvent) { element.detachEvent("on" + event, listener); } else { element["on" + event] = null; } } // 實現對click事件的綁定 function addClickEvent(element, listener) { addEvent(element, "click", listener); } // 實現對於按Enter鍵時的事件綁定 function addEnterEvent(element, listener) { element.onkeydown = function(e) { e = e || window.event; if (e.keyCode === 13) { listener(); } } }
接下來咱們把上面幾個函數和$作一下結合,把他們變成$對象的一些方法
addEvent(element, event, listener) -> $.on(element, event, listener); removeEvent(element, event, listener) -> $.un(element, event, listener); addClickEvent(element, listener) -> $.click(element, listener); addEnterEvent(element, listener) -> $.enter(element, listener);
$.on = addEvent; $.un = removeEvent; $.click = addClickEvent; $.enter = addEnterEvent;
<li>
增長點擊事件的監聽//考慮這樣一個場景,咱們須要對一個列表裏全部的<li>增長點擊事件的監聽 function clickListener(event) { console.log(event); } //方法一:針對每個item去綁定事件,這樣顯然是一件很麻煩的事情。 $.click($("#item1"), clickListener); $.click($("#item2"), clickListener); $.click($("#item3"), clickListener); //方法二:經過本身寫的函數,取到id爲list這個ul裏面的全部li,而後經過遍歷給他們綁定事件。這樣咱們就不須要一個一個去綁定了。 each($("#list2").getElementsByTagName('li'), function(li) { addClickEvent(li, clickListener); }); // 再此基礎上考慮另外一個場景,加了一個按鈕,當點擊按鈕時,改變list裏面的項目。這個時候你再點擊一下li,綁定事件再也不生效了。 function renderList() { $("#list").innerHTML = '<li>new item</li>'; /* 須要從新綁定事件 // 當加入 // each($("#list").getElementsByTagName('li'), function(item) { $.click(item, clickListener); }); 點擊按鈕時綁定事件纔會從新生效*/ } function init() { each($("#list").getElementsByTagName('li'), function(item) { $.click(item, clickListener); }); $.click($("#btn"), renderList); } init();
// 方法三:事件代理,改變DOM結構或內容不須要從新綁定事件 // 先簡單一些 function renderList() { $("#list").innerHTML = '<li>new item</li>'; } $.click($("#btn"), renderList); function delegateEvent(element,tag,eventName,listener){ addEvent(element, eventName, function(event){ var target = event.target || event.srcElement; if(target.tagName.toLowerCase() == tag.toLowerCase()) { listener.call(target, event); } }); } $.delegate = delegateEvent; var clickHandle = function (event) { alert(event); } // 使用示例 // 仍是上面那段HTML,實現對list這個ul裏面全部li的click事件進行響應 $.delegate($("#list"), "li", "click", clickHandle); // 這時改變DOM結構不須要從新綁定事件了。
簡單來說,當須要爲多個子元素添加事件時,能夠把事件加在父元素上,在DOM2級事件的冒泡階段父元素事件被觸發,因而底下全部子元素也一併添加了事件。
// 實現如下函數 // 判斷是否爲IE瀏覽器,返回-1或者版本號 function isIE() { // your implement } // 設置cookie function setCookie(cookieName, cookieValue, expiredays) { // your implement } // 獲取cookie值 function getCookie(cookieName) { // your implement }
//判斷是否爲IE瀏覽器,返回-1或者版本號 function isIE() { var s = navigator.userAgent.toLowerCase(); console.log(s); //ie10的信息: //mozilla/5.0 (compatible; msie 10.0; windows nt 6.2; trident/6.0) //ie11的信息: //mozilla/5.0 (windows nt 6.1; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; .net4.0c; .net4.0e; infopath.2; rv:11.0) like gecko var ie = s.match(/rv:([\d.]+)/) || s.match(/msie ([\d.]+)/); if (ie) { return ie[1]; } else { return -1; } }
// 設置cookie function setCookie(cookieName, cookieValue, expiredays) { var oDate = new Date(); oDate.setDate(oDate.getDate + expiredays); document.cookie = cookieName + '=' + cookieValue + ';expires=' + oDate; } // 獲取cookie function getCookie(cookieName) { var arr = document.cookie.split("; "); // 多條cookie以分號加空格隔開 for (var i = 0; i < arr.length; i++) { var arr2 = arr[i].split("="); if (arr2[0] === cookieName) { return arr2[1]; } } return ""; } // 移除cookie function removeCookie(cookieName) { setCookie(cookieName, "1", -1); // 把有效時間設置爲-1 }
學習Ajax,並嘗試本身封裝一個Ajax方法。實現以下方法:
// function ajax(url, options) { // your implement } // 使用示例: ajax( 'http://localhost:8080/server/ajaxtest', { data: { name: 'simon', password: '123456' }, onsuccess: function (responseText, xhr) { console.log(responseText); } } );
function ajax(url, options) { var dataResult; //結果data // 處理data if (typeof(options.data) === 'object') { var str = ''; for (var c in options.data) { str = str + c + '=' + options.data[c] + '&'; } dataResult = str.substring(0, str.length - 1); } // 處理type options.type = options.type || 'GET'; //獲取XMLHttpRequest對象 var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); // 發送請求 xhr.open(options.type, url, true); if (options.type == 'GET') { xhr.send(null); } else { xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(dataResult); } // readyState xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { if (options.onsuccess) { options.onsuccess(xhr.responseText, xhr.responseXML); } } else { if (options.onfail) { options.onfail(); } } } }; }