瘋狂Html+CSS+JS 中JS總結

jopen 9年前發布 | 55K 次閱讀 前端技術 HTML

0 總結

本書的JS

  1. 第一章有講語法有挺多常見的坑點和原理解釋很不錯
  2. 第二章DOM編程講述了挺多API
  3. 第三章事件處理機制其實對事件中的this關鍵字和事件傳播順序講解還不錯
  4. 第四章WebStorage本地存儲例子鮮明
  5. 第五章Worker應付復雜的js操作
  6. 第六章客戶端通信WebSocket挺有用,可以實現用戶與用戶在瀏覽器中互動
  7. </ol>

    1. JavaScript語法

    1.1 執行js代碼

    1. javascript:alert(‘執行js’);
    2. <script>alert("執行js")</script>
    3. </ol>

      1.2 變量賦值

      var a = 1;//顯式
      a =1; //隱式

      1.3 全局變量與局部變量

      ...
      var scope = "全局變量";
      function test(){
          alert(scope); // undefiend
          var scope = "局部變量";
          alert(scope); // 局部變量
      }

      因為全局變量被局部變量覆蓋了.雖然局部變量的scope還沒賦值,但是已經在方法里”占”上位置了.

      但如果把局部變量的var刪了,就會先輸出全局變量后輸出局部變量,因為沒有var在方法里給局部變量”占”位置;

      1.4 浮點數

      var a =.333
      var b = a * 5;
      alert(b);

      得出的結果是 1.66499999999999999

      所以在js中判斷浮點數是否相等 建議判斷兩者的差值是否小于一個足夠的數(例如0.0000000000001)

      1.5 字符串

      js中沒有字符類型變量 “”與’‘一致

      var s ="abcdefg"

      //b = "def" b = s.slice(3, -1);</pre>

      1.6 字符串的正則表達式方法中

      1. match()返回匹配的字符串(數組或null),可加/g進行全局匹配多個
      2. search()返回匹配的索引值 單個
      3. </ol>

        1.7 undefined和null

        null == undefined //true

        null === undefined //false</pre>

        undefined 是沒設值

        null則是設定了為null值

        1.8 運算符

        //逗號運算符 取最右返回值
        a = (b =5 , c = 7 , d =56) //a =56

        a = void(b =5 , c = 7 , d =56) //a = undefined</pre>

        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); // "用戶自定義異常" }</pre>

        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</pre>

        這樣的好處是什么,如果直接定義function 它實際上也是創建了一個對象

        1.11.2 函數既對象

        var hello = function(){...};

        hello instanceof Function //true;

        hello instanceof Object //true;

        alert(heelo) //輸出函數源代碼</pre>

        1.11.3 調用函數方式的不同

        1. 直接調用函數 返回return的值或void
        2. new 函數 得到的都是對象 - -…….
        3. </ol>

          1.11.4 this關鍵字.

          在函數中使用this.變量 該變量就是函數的實例變量,而非局部變量,無論它在哪里.

          函數可依附在類中.如沒指定 則依附在winodw對象中

          var hello =function(){...}

          window.hello();

          var p = { wark: function(){...} } p.wark();</pre>

          1.11.5 函數中的變量有三種

          function Person(){
              //局部變量 只能在函數里訪問
              var id ;

          //實例屬性 通過對象.訪問
          this.age ;
          
          //類屬性 通過Patient.name訪問 與static類似
          Person.name ;
          

          }</pre>

          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 類屬性也是可以動態添加的</pre>

          1.11.7 調用函數的三種方式

          1. 直接調用

            windows.alert();
             //or
             alert();
            </li>

          2. call()調用

            作用:動態地傳入一個函數引用

            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); });</pre>

            call()調用函數語法為:函數引用.call(調用者,參數1,參數2...)

            直接調用函數語法為:調用者.函數(參數1,參數2 ...)=函數.call(調用者,參數1,參數2 ...)

            </li>

          3. apply()調用

            apply和()call()基本相似,區別如下:

            1. 通過call()調用函數時,括號必須詳細列出每個參數
            2. 通過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</pre></li> </ol> </li> </ol>

              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</pre>

              來爽一發貓學狗叫?.

              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</pre>

              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]</pre>

              復合類型的傳遞為值傳遞,原person和參數person指向同一javascript對象,所以當改變age的時候,是在改變javascript對象的age,但是參數person賦值為null,原person并無改變.

              1.11.10 空參數

              function text(person){
                  alert( typeof parson);
              }

              text(); //undefined</pre>

              所以對于弱類型,方法重載是無作用的,因為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'變量. }</pre>

              1.11.12 繼承和prototype

              在一個類(函數)中定義一個函數會導致

              1. 性能低下:每次new一個類 都會生成一個函數
              2. 函數中若引用類的局部變量會產生閉包 導致局部變量一直存在

                function Person(){
                     var local = "局部變量"
                     this.info = function(){
                         //產生閉包
                         alert(local);
                     }
                 }

                var person = new Person(); person.ifno(); // 局部變量</pre></li> </ol>

                解決方案:prototype

                增加了prototype屬性的類可視為繼承了原先的類(偽繼承)

                function Person(){...}

                var person = new Person();

                //person.wark(); 程序報錯wark不存在 Person.prototype.wark = function(){...}

                person.wark(); //ok</pre>

                在prototype之前實例化的類會具有wark方法嗎? 有的,因為prototype這樣并不會產生一個新的類,而是直接動態的往Person里加函數.

                1.12 創建對象三種方式

                //(單身汪別說我不教你)

                1. new關鍵字調用構造器創建對象

                  function Person(name){...}
                   var person_1 = new Person();
                   var person_2 = new Person('K'); //js不存在方法重載,空參數undefined頂替
                  </li>

                2. 使用Object直接創建對象

                  var my_obj = new Object();
                   my_ojb.name = 'K';
                   my_obj.handsome = function(){...}

                  function text(){...} my_obj.text = text;//不要添加(),不然會認為是調用方法</pre></li>

                3. JSON創建對象

                  ver person = {
                       name : 'K',
                       school : ['ChangAn','TianJin'],
                       girl_friends :[
                           {
                               name : 'Haski',
                               age : 11
                           },
                           {
                               name : 'Samoyed',
                               age : '8'
                           }
                       ]
                   }

                  alert(person.girl_friends[0].name); //Haski</pre></li> </ol>

                  2 DOM編程

                  DOM操作其實JQuery已經做得很好了,這里簡單補充一下原生JS的知識

                  HTML文檔中只有一個根節點

                  2.1 訪問HTML元素

                  1. id getElementById(‘id’); or getElementsByName(‘name’);
                  2. 根據節點關系

                    Node parentNode: 返回父節點
                     Node previousSibling: 返回前一個兄弟節點
                     Node nextSibling: 飯后后一個兄弟節點
                     Node[] childNodes 返回當前節點的所有節點
                     Node[] getElementsByTagName('標簽名稱'): 返回當前節點具有制定標簽的子節點
                     //注意ol標簽的子標簽IE8和其他瀏覽器不一樣(其他瀏覽器會把ol下的li和其后面的空白分別當成2個節點,IE8則不會)
                    </li> </ol>

                    2.2 增加HTML函數

                    1. document.createElement(“標簽名”);
                    2. 復制節點 var node = ul.firstChild.nextSibling.cloneNode(boolean),boolean為true時,復制所有所有后代節點.false則僅復制當前節點.clone了節點以后還要找一個節點添加進去.
                    3. </ol>

                      2.3 添加節點

                      1. appendChild(Node);添加為當前節點的最后一個子節點
                      2. inserBefore(newNode,refNode);在refNode前添加newNode
                      3. replaceChild(newChild,oldChild);替換節點
                      4. 增加select選項 new Option(text,value,defaultSelected,selected);
                      5. </ol>

                        2.4 刪除節點

                        1. removeChild(oldNode);
                        2. </ol>

                          2.5 window對象

                          1. 返回上一個頁面: back()
                          2. window.href: 當前url
                          3. window.width: 屏幕橫向分辨率
                          4. window.height: 屏幕縱向分辨率
                          5. 遍歷window.screen,包含所以屏幕屬性

                            for(var propName in window.screen){
                                 alert(propName+":" +screent[propname]);
                             }
                            </li>

                          6. cofrim(‘標題’); 能彈出是否確認的提示框

                            </li>

                          7. prompt(‘標題’); 能彈出一個文本輸入框輸入.
                          8. 定時器:setInterVal,clearInterval()

                            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);
                            </li> </ol>

                            2.6 navigator和地理位置

                            navigator漢堡瀏覽器所有信息,遍歷循環獲取信息

                            for(var propName in window.navigator){
                                alert(propName + ":" + window.navigator[propName]);
                            }

                            HTML5新增geolocation屬性

                            Geolocation提供的方法

                            1. getCurrentPosition(onSuccess,onError,options)
                            2. int watchCurrentPostion(OnSuccess,onError,options),周期性調用getCurrentPosition,返回的int代表這個”監聽器”的ID,用來clearWatch(watchID)取消監聽
                            3. clearWatch(watchID),用于取消watchCurrentPosition
                            4. </ol>

                              上面的前兩個方法的options參數是一個對象,可包含3個變量

                              1. enabelHighAccuracy(是否制定高精度地理位置)
                              2. tiemout 設置超時時長
                              3. maximumAge,設置緩存時間
                              4. </ol>

                                例子:

                                var geoHandler = function(position){
                                    var geoMsg = "用戶地址位置是 : <br/>"
                                    geoMsg += "timestamp屬性為 :" + position.timestamp + "<br/>"http://獲取位置的時間
                                    var cords =position.coords;
                                    for(var prop in coords ){
                                        geoMsg += prop + ": " + coords[prop] +"<br/>"http://經緯度,移動速度等
                                    }
                                    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 });</pre>

                                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): 未知方式

                                redirectCount: 重定向次數

                                3 事件處理機制

                                3.1 常見事件

                                1. onabort: 圖片加載終端
                                2. onblur: 失去焦點
                                3. onchange: 表單域更改
                                4. onclick: 點擊
                                5. onerror: 圖片加載出錯
                                6. onfocus: 獲得焦點
                                7. onkeydown: 按下鼠標
                                8. onkeypress: 當焦點在當前元素上,單擊鍵盤某個鍵觸發
                                9. onkeyup: 當焦點在當前元素上,松開某個鍵觸發
                                10. onload: 某個對象加載完畢,適用于img,oframe,body
                                11. onunload: 當某個對象從窗口下卸載觸發,適用于img,oframe,body
                                12. onmousedown: 焦點停留在當前元素上,按下鼠標觸發
                                13. onmousemore: 當焦點在當前元素上,鼠標移動到該元素
                                14. onmouseout: 鼠標移出當前元素觸發
                                15. onmouseover: 鼠標移動到該元素觸發
                                16. onmouseup: 焦點在當前元素,松開鼠標時觸發
                                17. onreset: 重置表單時觸發
                                18. onsubmit: 表單提交觸發
                                19. </ol>

                                  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);</pre>

                                  阻止事件傳播

                                  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);</pre>

                                  點擊按鈕1,按鈕執行了前面按鈕一被點擊了提示語句后,將點擊事件轉給了按鈕2,按鈕2執行自身的點擊事件.

                                  4 本地存儲與離線應用

                                  4.1 Web Storage

                                  使用理由之一Cookie的局限性:

                                  1. Cookie大小被限制為4KB
                                  2. Cookie會包含在每次HTTP請求中
                                  3. Cookie網絡傳輸未加密(除非整個應用都使用SSL)
                                  4. </ol>

                                    Web Storage分兩種

                                    Session Storage: 生命周期與用戶Session一致(用戶Session是指:用戶從訪問網址到離開網址/關閉瀏覽器)

                                    Local Storage: 保存在用戶的磁盤中,失效的方式為用戶/程序顯示刪除.

                                    Web Storage的方法有

                                    1. length: 返回key-value對數
                                    2. key(index): 返回第index個key
                                    3. getItem(key): 獲取key對應的value
                                    4. set(key,value): 設置key-value
                                    5. removeItem(key): 刪除key-value
                                    6. clear(): 清除所有key-value
                                    7. </ol>

                                      Web Storage包含在window對象中

                                      當value為對象時,建議用JSON存儲

                                      4.2 構建離線應用

                                      1. 在html標簽中修改

                                        //表明該頁使用index.manifest文件
                                         <html manifest="index.manifest">
                                        </li>

                                      2. index.mainfest文件

                                        CACHE MANIFEST
                                         //第一行必須為上述字符
                                         //指定版本號

                                        version 1

                                        //本地緩存資源 CACHE inedx.html logo.jpg //不緩存的資源 NETWORK * //前者表示在線狀態使用的資源,后者代表離線狀態使用的資源 FALLBACK test.js offline.js</pre></li>

                                      3. Tomcat為例,天津映射文件

                                        <!--conf的web.xml根元素中增加MIME映射-->
                                         <mine-mapping>
                                             <extension>manifest</extension>
                                             <mine-type>text/cache-mainfest</mime-type>
                                         </mime-mapping>
                                        </li> </ol>

                                        啟動應用后,頁面可刷新(即使離線狀態),并使用離線時候的資源

                                        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屬性:

                                        1. UNCACHE: 主機沒開啟離線功能.
                                        2. IDLE: 空閑狀態.
                                        3. CHECKING: 正在檢查本地manifest和服務器中manifest的差異
                                        4. DOWNLOADING: 正在下載需要的緩存數據
                                        5. OBSOLETE: 緩存已經過期
                                        6. </ol>

                                          常用方法

                                          1. void update(): 強制檢查服務器的mainfest文件是否有更新
                                          2. void swapCache(): 更新緩存,只能在applicationCache的updateReady事件被觸發時調用.

                                            setInterval(function(){
                                                 applicationCache.update()
                                             },2000);

                                            applicationCache.onupdateready = function(){ if(confirm("已從遠程服務器下載了需要的緩存,是否更新?")){ applicationCache.swapCache(); location.reload(); } }</pre>

                                            4.2.3 離線應用的事件與監聽

                                            </li> </ol>

                                            訪問html頁面過程

                                            1. 瀏覽器請求index.html
                                            2. 服務器返回index.html
                                            3. 瀏覽器頁面是否制定manifest屬性,若制定,觸發checking事件,檢查服務器中的manifest文件是否存在,不存在則觸發error事件,不會制定第六部及其后續步驟
                                            4. 瀏覽器解析index.html,請求該頁其他資源.
                                            5. 服務器返回所以請求
                                            6. 瀏覽器處理mainfest文件,重新請求manifest文件中的所以頁面,包括index.html頁面,前面下載過的資源,扔會再下一遍.
                                            7. 服務器返回所以要求被要求緩存的資源
                                            8. 瀏覽器開始下載需要在本地緩存的資源,開始下載時觸發ondownloading事件,在下載過程中不斷觸發onprogress事件.以便開發人員了解下載進度.
                                            9. 下載完成后觸發oncache事件.緩存完成
                                            10. </ol>

                                              當用戶再訪問index.html時,前面1~5完全相同,接下來檢測mainfest文件是否有改變.

                                              1. 沒有改變觸發onnoupdate事件,結束.
                                              2. mainfest改變,執行第7,8部,當所以文件本地緩存下載完畢后,瀏覽器觸發onupdateready事件,而不會觸發oncached事件.
                                              3. </ol>

                                                5 使用worker創建多線程

                                                worker中無法使用DOM、alert等與界面有關的操作.

                                                使用理由:防止js阻塞主線程的js運行

                                                WorkerAPI

                                                1. onmessage: 獲取前臺js提交過來的數據
                                                2. postMessage(data): 前臺js通過postMessage觸發Worker對象的onmessage事件.
                                                3. importScripts(urls),導入多個js,importScripts(“a.js”,“b.js”);
                                                4. sessionStorge/localStorage: 使用Worker操作Storage本地存儲
                                                5. Worker: 創建新的Worker對象啟動嵌套線程
                                                6. XMLHttpRequest: Worker使用XMLHttpRequest發送異步請求.
                                                7. navigator: 與window的location屬性類似
                                                8. location: 與window的location屬性相似
                                                9. self: WorkerGlobalScope對象,代表當前Worker線程自身作用域.調用self的close()結束線程
                                                10. setTimeout()/seInterval()/eval()/inNaN()/parseInt,等與界面無關的js核心函數,包括Array/Data/Math/Number/Object/String等.
                                                11. </ol>

                                                  寫一段找出輸入start和end之間素數的線程.

                                                  worker.js代碼

                                                  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可嵌套.

                                                  6 客戶端通信

                                                  WebSocket: 服務器主動推送信息/客戶端實時推送數據到服務器

                                                  6.1 跨文檔通信

                                                  window對象新增方法

                                                  1. targetWindow.postMessage(message,targetOrigin): 該方法用戶向targetWindow中狀態的HTML發送信息,targetOrigin表示接收html的域名.
                                                  2. onmessage: 調用方法:windows.onmessage =function(event){…}

                                                    event中的屬性:

                                                    1. data: 數據
                                                    2. orgin: 發送消息window的源域名
                                                    3. lastEventID: 返回發送消失時間的ID
                                                    4. source: 返回發送消息的窗口
                                                    5. </ol> </li> </ol>

                                                      html想發送要做

                                                      1. 獲取接收消息的window對象
                                                      2. 調用接收消息的window對象的postMessage(any message)方法
                                                      3. </ol>

                                                        html想接收要做

                                                        1. 本html綁定事件window.message = function(event){…};
                                                        2. </ol>

                                                          跨文檔消息傳遞

                                                          //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); }</pre>

                                                          結果:

                                                          alert(接收到消息拉!傳輸消息);

                                                          alert(回傳消息);

                                                          注意!一定要判斷發送方的域名!!!!!一定要判斷發送方的域名!!!!!一定要判斷發送方的域名!!!!!

                                                          6.2 WebSocket與服務器通信

                                                          以前方案:

                                                          1. 周期發送請求
                                                          2. 頁面使用隱藏窗口與服務器長連接
                                                          3. </ol>

                                                            WebSocket方法

                                                            1. send(“數據”);向服務器發送數據.
                                                            2. close();關閉該WebSocket.
                                                            3. </ol>

                                                              WebSocket監聽事件

                                                              1. onopen: 當WebSocket建立網絡連接觸發該.
                                                              2. onerror: 網絡連接錯誤
                                                              3. onclose: WebScokt被關閉觸發
                                                              4. onmessage: WebSocket接收到服務器數據時
                                                              5. </ol>

                                                                WebSocket屬性

                                                                1. readyState

                                                                  1.1 CONNECTING(0): WebSocket正在嘗試連接

                                                                  1.2 OPEN(1): 已經連接

                                                                  1.3 CLOSING(2): 正在關閉連接

                                                                  1.4 CLOSED(3): 已經關閉連接

                                                                  </li> </ol>

                                                                  WebSocket與服務器通信步驟

                                                                  1. WebSocket.Constructor(url,[DOMString protocols]);創建WebSocket對象
                                                                  2. 發送信息: WebSocket對象的send()
                                                                  3. 接收信息: WebSocket對象的onmessage屬性綁定函數;
                                                                  4. </ol>

                                                                    實現客戶端多人聊天,JAVA為例

                                                                    客戶端代碼:

                                                                    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=""; }

                                                                    ...</pre>

                                                                    服務端代碼

                                                                    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); } }</pre>來自:http://mzkmzk.github.io/blog/2015/10/05/amazeing-js/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!