本書的JSjavascript
1.1 執行js代碼html
javascript:alert(‘執行js’);//通常放在超連接中,用戶點擊即執行,
<script>alert("執行js")</script>前端
1.2 變量賦值java
var a = 1;//顯式 a =1; //隱式
1.3 全局變量與局部變量node
... var scope = "全局變量"; function test(){ alert(scope); // undefiend var scope = "局部變量"; alert(scope); // 局部變量 }
由於全局變量被局部變量覆蓋了.雖然局部變量的scope還沒賦值,可是已經在方法裏」佔」上位置了.
但若是把局部變量的var刪了,就會先輸出全局變量後輸出局部變量,由於沒有var在方法裏給局部變量」佔」位置;git
1.4 浮點數github
var a =.333 var b = a * 5; alert(b);
得出的結果是 1.66499999999999999
因此在js中判斷浮點數是否相等 建議判斷二者的差值是否小於一個足夠的數(例如0.0000000000001)web
1.5 字符串正則表達式
js中沒有字符類型變量 「」與’‘一致編程
var s ="abcdefg" //b = "def" b = s.slice(3, -1);
1.6 字符串的正則表達式方法中
1.7 undefined和null
null == undefined //true null === undefined //false
undefined 是沒設值
null則是設定了爲null值
1.8 運算符
//逗號運算符 取最右返回值 a = (b =5 , c = 7 , d =56) //a =56 a = void(b =5 , c = 7 , d =56) //a = undefined
1.9 typeof和instanceof
typeof 用來得到 實例類型 :
typeof("123"); //string
instanceof 判斷變量是否爲某類的實例
var a = [4,5]; alert(a instanceof Array); //true
1.10 語句
拋出異常
throw new Error("用戶自定義異常"); //通常用於終止程序和返回錯誤提示是個不錯的選擇; try{ }catch(e){ alert(e.message); // "用戶自定義異常" }
for in
//這回輸出瀏覽器的全部屬性,作瀏覽器兼容以前能夠考慮看看. for( prop_name in navigator){ document.wrti(prop_name + " : " + navigator[propname]); }
跳出命名for
outer: for(...){ for(...){ ... continue outer; } }
1.11 函數
js 容許先調用函數 再定義函數
1.11.1 定義匿名函數
var show_name = function(name){ alert(name); } show_name("K"); //K
這樣的好處是什麼,若是直接定義function 它實際上也是建立了一個對象
1.11.2 函數既對象
var hello = function(){...}; hello instanceof Function //true; hello instanceof Object //true; alert(heelo) //輸出函數源代碼
1.11.3 調用函數方式的不一樣
1.11.4 this關鍵字.
var hello =function(){...} window.hello(); var p = { wark: function(){...} } p.wark();
1.11.5 函數中的變量有三種
function Person(){ //局部變量 只能在函數裏訪問 var id ; //實例屬性 經過對象.訪問 this.age ; //類屬性 經過Patient.name訪問 與static相似 Person.name ; }
1.11.6 js是一種動態語言,能隨時給對象增長屬性和方法
function Student(){ }; var student =new Student(); //動態增長name屬性 student.name = 'K'; alert(sutdent.name) //K Student.age =22 ; alert(Student.age); //22 類屬性也是能夠動態添加的
1.11.7 調用函數的三種方式
windows.alert(); //or alert();
var each = function(array,fn){ for(var index in arrary){ //null表示以window爲調用者fn函數 fn.call(null,index,arrary[index]); } } each([4,20,3] , function(index ,ele){ alert("第 " + index "個元素是 : " + ele); });
call()調用函數語法爲:函數引用.call(調用者,參數1,參數2...)
直接調用函數語法爲:調用者.函數(參數1,參數2 ...) = 函數.call(調用者,參數1,參數2 ...)
apply()調用
apply和()call()基本類似,區別以下:
經過call()調用函數時,括號必須詳細列出每一個參數
經過apply()動態地調用函數時,能夠在括號中以arguments來表明全部參數
var myfun = function (a , b){ alert(a + " " +b); } myfun.call(window ,12 ,23); //12 23; myfun.apply(window ,[20 , 39]); //20 39 var example = function (num1 ,num2){ //直接調用arguments表明調用者(example,this表明example)時的傳入的全部參數 myfun.apply(this,arguments); } example(20,40) //20 40
1.11.8 函數的獨立性
在函數A中能夠定義函數B,可是函數B仍是獨立於函數A
function Person(name){ this.name = name; this.info = function(){ alert(this.name); } } var person =new Person('K'); person.info(); //K var name = 'K_window'; //因爲window爲調用者 ,this.name訪問的是window.name p.info.call(window); //K_window
來爽一發貓學狗叫?.
function Dog(name,bark){ this.name = name; this.bark = bark; this.info =function(){ alert(this.name + " " + this.bark); } } function Cat(name){ this.name =name; } var dog = new Dog("K","汪汪!"); var cat = new Cat("K_2"); dog.info.call(cat); //K_2 undefined
1.11.9 參數傳遞方式
和JAVA同樣 都是值傳遞拉~.
基本類型
function change(arg){ arg =10 ; alert(arg); } var x = 5; alert(x); //5 change(x); //10 alert(x); //5
複合類型
function change(person){ person.age = 10; alert(person.age); person = null; } var person = {age : 5}; alert(person.age); //5 change(person); //10 alert(person.age); // 10 alert(person); // []object Object]
複合類型的傳遞爲值傳遞,原person和參數person指向同一javascript對象,因此當改變age的時候,是在改變javascript對象的age,可是參數person賦值爲null,原person並沒有改變.
1.11.10 空參數
function text(person){ alert( typeof parson); } text(); //undefined
因此對於弱類型,方法重載是無做用的,由於js會把空參數當作undefined傳遞進去;
同名函數,後面出現的會覆蓋前面的,不管參數個數是多少.
1.11.11 對象和關聯數組
javascript和Map有點相似,當key爲對象,value爲函數,該該函數就是對象的方法,當key爲對象,value爲基本類型,則該基本類型爲對象的屬性.(以上爲便於理解,切勿細琢)因此訪問屬性時,能夠obj.propName也能夠obj[propName].
但有時候咱們只能用obj[propName],由於.propName不能把propName當作變量處理,而是把他當成’propName’字符串
function Person(name){ this.name =name; this.info = function(){ alert(K); } } var person = new Person("K"); //遍歷person屬性 for (propName in person){ alert(p[propName]);//alet K info源代碼 假如此處用p.propName則undefined,由於Person無'propName'變量. }
1.11.12 繼承和prototype
在一個類(函數)中定義一個函數會致使
function Person(){ var local = "局部變量" this.info = function(){ //產生閉包 alert(local); } } var person = new Person(); person.ifno(); // 局部變量
解決方案:prototype
增長了prototype屬性的類可視爲繼承了原先的類(僞繼承)
function Person(){...} var person = new Person(); //person.wark(); 程序報錯wark不存在 Person.prototype.wark = function(){...} person.wark(); //ok
在prototype以前實例化的類會具備wark方法嗎? 有的,由於prototype這樣並不會產生一個新的類,而是直接動態的往Person里加函數.
判斷某方法是否繼承了該對象
該對象.prototype['某方法'] != undefined; var test = new 該對象(); test.某方法 !=undefined ;
1.12 建立對象三種方式
//(單身汪別說我不教你)
function Person(name){...} var person_1 = new Person(); var person_2 = new Person('K'); //js不存在方法重載,空參數undefined頂替
var my_obj = new Object(); my_ojb.name = 'K'; my_obj.handsome = function(){...} function text(){...} my_obj.text = text;//不要添加(),否則會認爲是調用方法
ver person = { name : 'K', school : ['ChangAn','TianJin'], girl_friends :[ { name : 'Haski', age : 11 }, { name : 'Samoyed', age : '8' } ] } alert(person.girl_friends[0].name); //Haski
DOM操做其實JQuery已經作得很好了,這裏簡單補充一下原生JS的知識
HTML文檔中只有一個根節點
2.1 訪問HTML元素
Node parentNode: 返回父節點 Node previousSibling: 返回前一個兄弟節點 Node nextSibling: 飯後後一個兄弟節點 Node[] childNodes 返回當前節點的全部節點 Node[] getElementsByTagName('標籤名稱'): 返回當前節點具備制定標籤的子節點 //注意ol標籤的子標籤IE8和其餘瀏覽器不同(其餘瀏覽器會把ol下的li和其後面的空白分別當成2個節點,IE8則不會)
2.2 增長HTML函數
2.3 添加節點
2.4 刪除節點
2.5 window對象
for(var propName in window.screen){ alert(propName+":" +screent[propname]); }
var timer; var cur = new Date().getTime(); var setTime = function(){ document.getElementById("tm").innerHTML = new Date().toLocationString(); if(new Date().getTime- cur > 60 *1000){ clearInterval(timer); } } //每1S執行一次,執行了60次就暫停 timer = window.setInterval("setTime()",1000);
2.6 navigator和地理位置
navigator漢堡瀏覽器全部信息,遍歷循環獲取信息
for(var propName in window.navigator){ alert(propName + ":" + window.navigator[propName]); }
HTML5新增geolocation屬性
Geolocation提供的方法
上面的前兩個方法的options參數是一個對象,可包含3個變量
var geoHandler = function(position){ var geoMsg = "用戶地址位置是 : <br/>" geoMsg += "timestamp屬性爲 :" + position.timestamp + "<br/>"//獲取位置的時間 var cords =position.coords; for(var prop in coords ){ geoMsg += prop + ": " + coords[prop] +"<br/>"//經緯度,移動速度等 } document.writeln(geoMsg); } var errorHandler = function(error){ var errMsg = { 1: '用戶拒絕了位置服務' 2: '沒法獲取地址位置信息' 3: '獲取地理位置信息超時' }; alert(error[error.code]); } navigator.geolocation.getCurrentPosition(geoHandler , errorHandler , { enableHighAccuracy:true, maximuAge:1000 });
2.7 HTML5新增瀏覽器分析
實現該功能主要經過performance對象
其中的(PerformanceTiming)timing屬性包含加載時間相關的屬性
另外(PerformanceNavigation)navigation,主要屬性有
type :
TYPE_NAVIGATE(數值爲0): 超連接/輸入url TYPE_RELOAD(1): 從新加載方式,diaoyonglocation.reload()等 TYPE_BACK_FORWARD(2): 經過瀏覽器的前進方式 TYPE_RESERVED(255): 未知方式
3 事件處理機制
3.1 常見事件
3.2 事件處理和this
p.info = function(){ alert(this.name); } document.getElementById("bt").onclick = p.info//this指向'bt'控件 document.getElementById("bt").onclick = new function (){ p.info();} //this老是指向p
注意表單設置id爲x和name爲y時候,至關於表單建立了x屬性和y屬性,因此id和name不能是關鍵字submit等
3.3 DOM
建立監聽事件
objectTarget.addEventListener(「eventType」,handler,capture),第一個參數表示綁定的事件,如click、keypress之類的,第二個制定綁定的函數,第3個位boolean,true表示監聽捕獲階段,false表示監聽冒泡階段
objectTarget.removeEventListener(「eventType」,handler,captureFlag): 刪除綁定事件
捕獲狀態階段的綁定事件先執行,事件冒泡狀態階段的綁定事件後執行. 捕獲狀態階段從外往內觸發,事件冒泡狀態階段從內往外觸發.
綁定例子
var got_click = function (event){ for ( event_one in event){ alert(event_one + " : " + event[event_one]); } } document.getElementByID("test").addEventListener("cilck",got_click,true);
阻止事件傳播
event.stopPropagation();
取消事件的默認行爲,如跳轉頁面等,但不會阻止事件傳播.
event.preventDefault();
3.3.1轉發事件
DOM提供了dispathEvent方法用於事件轉發,該方法屬於Node
target.dispathEvent(Event event),將event轉發到target上
DOM的dispath()必須轉發人工合成的Event事件
document.createEvent(String type),tpy參數用於指定事件類型,eg:普通事件Events,UI事件UIEvents,鼠標事件:MouseEvents
初始化事件
initEvent(具體參數...) initUIEvent(具體參數...) intMouseEvent(具體參數...) //例子 <input id="bt1"> <input id="bt2"> ... var rd =function(evt){ alert("事件冒泡階段: " + evt.currentTarget.value +"被點擊了"); var e =document.createEvent("Evnets"); e.initEvent("click",true,false);//true表示是否支持冒泡,false表示是否有默認行爲 document.getElementById("bn2").dispathEvent(e); } var go_click = function (evt){ alert("事件冒泡階段: " + evt.currentTarget.value); } document.getElementById("bn1").addEventListener("click",rd,false); document.getElementById("bn2").addEventListener("click",go_click,false);; //點解按鈕一結果 alert(事件冒泡階段: 按鈕一被點擊了); alert(事件冒泡階段:按鈕2);
點擊按鈕1,按鈕執行了前面按鈕一被點擊了提示語句後,將點擊事件轉給了按鈕2,按鈕2執行自身的點擊事件.
4.1 Web Storage
使用理由之一Cookie的侷限性:
Cookie大小被限制爲4KB
Cookie會包含在每次HTTP請求中
Cookie網絡傳輸未加密(除非整個應用都使用SSL)
Web Storage分兩種
Session Storage: 生命週期與用戶Session一致(用戶Session是指:用戶從訪問網址到離開網址/關閉瀏覽器)
Local Storage: 保存在用戶的磁盤中,失效的方式爲用戶/程序顯示刪除.
Web Storage的方法有
length: 返回key-value對數
key(index): 返回第index個key
getItem(key): 獲取key對應的value
set(key,value): 設置key-value
removeItem(key): 刪除key-value
clear(): 清除全部key-value
Web Storage包含在window對象中
當value爲對象時,建議用JSON存儲
4.2 構建離線應用
//代表該頁使用index.manifest文件 <html manifest="index.manifest">
CACHE MANIFEST //第一行必須爲上述字符 //指定版本號 #version 1 //本地緩存資源 CACHE inedx.html logo.jpg //不緩存的資源 NETWORK * //前者表示在線狀態使用的資源,後者表明離線狀態使用的資源 FALLBACK test.js offline.js
<!--conf的web.xml根元素中增長MIME映射--> <mine-mapping> <extension>manifest</extension> <mine-type>text/cache-mainfest</mime-type> </mime-mapping>
啓動應用後,頁面可刷新(即便離線狀態),並使用離線時候的資源
4.2.1 判斷在線狀態
navigator.onLine屬性: true表示在線
online/offline事件: 當在線/離線狀態切換時,body上的online/offine事件會被觸發,沿着document.body、document和window冒泡
window.addEventListener("offline",function(){ alert("離線狀態") },true); if(navigator.onLine){ alert("在線"); }
4.2.2 applicationCache對象
js可經過applicationCache控制離線緩存.
status屬性:
經常使用方法
setInterval(function(){ applicationCache.update() },2000); applicationCache.onupdateready = function(){ if(confirm("已從遠程服務器下載了須要的緩存,是否更新?")){ applicationCache.swapCache(); location.reload(); } }
4.2.3 離線應用的事件與監聽
訪問html頁面過程
當用戶再訪問index.html時,前面1~5徹底相同,接下來檢測mainfest文件是否有改變.
worker中沒法使用DOM、alert等與界面有關的操做.
使用理由:防止js阻塞主線程的js運行
WorkerAPI
onmessage =function(event){ var data =JSON.parse(event.data); var start =data.start; var end =data.end; var result =""; search: for (var n =start; n <= end :n++){ if(n%i==0){ continue search; } result +=(n+","); } } postMessage(result);
網頁代碼
<input name="start" ...> <input name="end" ...> <input type=button inclick="cal();" ...> ... var car =function(){ var start = parseInt(document.getElementById("start").value); var end = parseInt(document.getElementById("end").value); //建立線程 var cal = new Worker("worker.js"); var data ={ "start" : srart, "end" : end }; //發送數據 cal.postMessage(JSON.stringify(data)); cal.onmessage = function (evnet){ alert(event); } }
並行的兩條Worker不能互相通訊,但Wroker可嵌套.
WebSocket: 服務器主動推送信息/客戶端實時推送數據到服務器
6.1 跨文檔通訊
window對象新增方法
html想發送要作
html想接收要作
//source.html var targetWin = window.open("接收方url",'_blank','windth=400,height=300'); targetWin.onload =function(){ targetWin.postMessage("傳輸消息","接收方域名"); } window.onmessage =function(event){ //忽略其餘域名發送的消息 if(event.orgin !="指定域名"){ return ; } alert(event.data); } //接收頁面.html window.onmessage = function(event){ //忽略其餘域名發送的消息 if(event.orgin !="指定域名"){ return ; } alert("接收到消息拉!"+event.data); event.source.postMessage("回傳消息",event.origin); }
結果:
alert(接收到消息拉!傳輸消息);
alert(回傳消息);
注意!必定要判斷髮送方的域名!!!!!必定要判斷髮送方的域名!!!!!必定要判斷髮送方的域名!!!!!
之前方案:
WebSocket方法
WebSocket監聽事件
WebSocket屬性
WebSocket與服務器通訊步驟
客戶端代碼:
var web_socket =new WebSocket("ws://域名:端口"); web_socket.onopen =function(){ web_socket.onmessage =function(event){ document.getElementById('show').innerHTML += event.data +"</br>" } }; var sendMsg =function(val){ var inputElement = document.getElementByID('msg'); webSocket.send(inputElement.value); inputElement.value=""; } ...
服務端代碼
<article class="post" > import java.io.*; import java.net.*; import java.nio.charset.Charset; import java.security.MessageDigest; import java.util.regex.*; import java.util.*; import sun.misc.BASE64Encoder; public class ChatServer { // 記錄全部的客戶端Soccket public static List<Socket> clientSockets = new ArrayList<Socket>(); public ChatServer()throws IOException { // 建立ServerSocket,準備接受客戶端鏈接 ServerSocket ss = new ServerSocket(30000); while(true) { // 接收到客戶端鏈接 Socket socket = ss.accept(); // 將客戶端Socket添加到clientSockets集合中 clientSockets.add(socket); // 啓動線程 new ServerThread(socket).start(); } } public static void main(String[] args) throws Exception{ new ChatServer(); } } class ServerThread extends Thread { private Socket socket; public ServerThread(Socket socket) { this.socket = socket; } public void run() { try { // 獲得Socket對應的輸入流 InputStream in = socket.getInputStream(); // 獲得Socket對應的輸出流 OutputStream out = socket.getOutputStream(); byte[] buff = new byte[1024]; String req = ""; // 讀取數據,此時創建與WebSocket的"握手"。 int count = in.read(buff); // 若是讀取的數據長度大於0 if(count > 0) { // 將讀取的數據轉化爲字符串 req = new String(buff , 0 , count); System.out.println("握手請求:" + req); // 獲取WebSocket的key String secKey = getSecWebSocketKey(req); System.out.println("secKey = " + secKey); String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: " + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + getSecWebSocketAccept(secKey) + "\r\n\r\n"; System.out.println("secAccept = " + getSecWebSocketAccept(secKey)); out.write(response.getBytes()); } int hasRead = 0; // 不斷讀取WebSocket發送過來的數據 while((hasRead = in.read(buff)) > 0){ System.out.println("接收的字節數:" + hasRead); /* 由於WebSocket發送過來的數據遵循了必定的協議格式, 其中第3個〜第6個字節是數據掩碼。 從第7個字節開始纔是真正的有效數據。 所以程序使用第3個〜第6個字節對後面的數據進行了處理 */ for (int i = 0 ; i < hasRead - 6 ; i++ ){ buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]); } // 得到從瀏覽器發送過來的數據 String pushMsg = new String(buff , 6 , hasRead - 6 , "UTF-8"); // 遍歷Socket集合,依次向每一個Socket發送數據 for (Iterator<Socket> it = ChatServer.clientSockets.iterator() ; it.hasNext() ;) { try { Socket s = it.next(); // 發送數據時,第一個字節必須與讀到的第一個字節相同 byte[] pushHead = new byte[2]; pushHead[0] = buff[0]; // 發送數據時,第二個字節記錄發送數據的長度 pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length; // 發送前兩個字節 s.getOutputStream().write(pushHead); // 發送有效數據 s.getOutputStream().write(pushMsg.getBytes("UTF-8")); } catch (SocketException ex) { // 若是捕捉到異常,代表該Socket已經關閉 // 將該Socket從Socket集合中刪除 it.remove(); } } } } catch (Exception e) { e.printStackTrace(); } finally { try { // 關閉Socket socket.close(); } catch (IOException ex) { ex.printStackTrace(); } } } // 獲取WebSocket請求的SecKey private String getSecWebSocketKey(String req) { //構建正則表達式,獲取Sec-WebSocket-Key: 後面的內容 Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); Matcher m = p.matcher(req); if (m.find()) { // 提取Sec-WebSocket-Key String foundstring = m.group(); return foundstring.split(":")[1].trim(); } else { return null; } } // 根據WebSocket請求的SecKey計算SecAccept private String getSecWebSocketAccept(String key) throws Exception { String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; key += guid; MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(key.getBytes("ISO-8859-1") , 0 , key.length()); byte[] sha1Hash = md.digest(); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(sha1Hash); } } [javascript](http://mzkmzk.github.io/blog/categories/javascript/) </article> <a class="addthis_button_facebook_like" fb:like:layout="button_count" ></a><a class="addthis_button_tweet" ></a>
【我有一個前端學習交流QQ羣:328058344 若是你在學習前端的過程當中遇到什麼問題,歡迎來個人QQ羣提問,羣裏天天還會更新一些學習資源。禁止閒聊,非喜勿進。】