js基礎知識筆記

  1. <script>
    defer 腳本延遲執行,適用於外部腳本文件
    async 當即下載,不保證順序(建議不修改DOM,避免重繪)
    CDN加速 (Content Delivery Network,內容分發網絡) 提升訪問網站的響應速度javascript

    <script>
     function loadScript(){
        document.write(unescape("%3Cscript src='防錯文件' %3E%3C/script%3E"))
      }
    </script>
    <script src="cdn文件" onerror="loadScript()"></script>
  2. 內存
    js內存回收機制:解除引用
    內存溢出:內存不夠,系統會提示內存溢出,有時候會自動關閉軟件
    內存泄漏:未能釋放已經再也不使用的內存,不是指內存在物理上的消失,而是內存的浪費
    常見內存泄漏情形:1.全局變量、2.被忘記的Timers或者callbacks、3.閉包、4.DOM引用
  3. 閉包
    概念:有權訪問另外一個函數做用域的變量的函數
    做用:匿名自執行函數、結果緩存、封裝、實現類和繼承
  4. 函數封裝模式html

    //工廠模式:在函數中返回一個建立並返回一個對象
    function createClass0(params){
      var o = new Object();
      o.name = params;
      o.fn0 = function(){
        console.log(this.name);
      }
      return o;
    }
    
    var obj = createClass0(params);
    console.log(obj.constructor == createClass0); //false
    console.log(obj instanceof createClass0); //false
    
    //構造函數模式:es6的類也是經過該模式實現
    function Class0(params){
      this.name = params;
      this.fn0 = fn0;
      this.fn1 = function(){
        console.log(this.name)
      }
    }
    function fn0(){
      console.log(this.name)
    }
    
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //true
    console.log(obj instanceof Class0); //true
    
    //原型模式:屬性與方法掛在原型鏈上
    function Class0(){}
    Class0.prototype = {
      name: params,
      fn0: function(){
        console.log(this.name)
      }
    }
    var obj = new Class0();
    console.log(obj.constructor == Class0);//true
    console.log(obj instanceof Class0); //true
    Object.defineProperty(Class0.prototype,"constructor",{
      enumerable: false,
      value: Class0
    })
    console.log(obj.constructor == Class0); //false
    
    //動態原型模式:
    function Class0(params){
      this.name = params;
      if(typeof this.fn0 != "function"){
        Class0.prototype.fn0 = function(){
          console.log(this.name)
        }
      }
    }
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //true
    console.log(obj instanceof Class0); //true
    
    //寄生構造函數模式:
    function Class0(params){
      var o = new Object();
      o.name = params;
      return o;
    }
    
    var obj = new Class0(params);
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //穩妥構造函數模式:沒法訪問其屬性
    function Class0(params){
      var o = new Object();
      var name = params;
      o.fn0 = function(){
        console.log(name);
      }
      return o;
    }
    
    var obj = Class0(params);
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //繼承:js沒有藉口繼承,只有實現繼承,依靠原型鏈實現
    //經典繼承:借用構造函數
    function Class0(params){
      this.name0 = params;
      this.fn0 = function(){
        console.log(this.name);
      }
    }
    function subClass0(params){
      Class0.call(this,params);  
      this.name1 = params;
      subClass0.prototype.fn1 = function(){
        console.log(this.name1);
      }
    }
      
    var obj = new subClass0(params);
    console.log(obj.constructor == subClass0); //true
    console.log(obj instanceof subClass0); //true
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //false
    
    //組合繼承:es6類的繼承經過該模式實現
    function Class0(params){
      this.name0 = params;
      this.fn0 = function(){
        console.log(this.name0);
      }
    }
    function subClass0(params){
      Class0.call(this,params);
      this.name1 = params;
      subClass0.prototype.fn1 = function(){
        console.log(this.name1);
      }
    }
    subClass0.prototype = new Class0();
    subClass0.prototype.constructor = subClass0;
    
      
    var obj = new subClass0(params);
    console.log(obj.constructor == subClass0); //true
    console.log(obj instanceof subClass0); //true
    console.log(obj.constructor == Class0); //false
    console.log(obj instanceof Class0); //true
  5. BOM
    概念:瀏覽器對象模型
    核心對象:window,經過js訪問瀏覽器窗口的一個接口,也是ECMAScript規定的Global對象。
    窗口框架:frameiframe
    窗口位置:window.screenLeft/window.screenX,window.moveBy(x,y); window.moveTo(x,y);
    窗口大小:window.resizeTo(width,height); window.resizeBy(dWidth,dHeight);
    導航彈窗:let win = window.open("..."); win.close();
  6. location
    hashURLhash字符串
    host:服務器名稱和端口號
    hostname:服務器名稱
    href:當前加載頁面的完整URL
    pathnameURL中的目錄
    portURL中制定的端口號
    prptocol:頁面使用的協議
    searchURL的查詢字符串,以?開頭
    改變URL會生成新記錄,禁用歷史記錄跳轉可經過location.replace("...")實現
    刷新頁面:location.reload(); location.reload(true);
  7. navigatorjava

    離線檢測:onLine
    地理信息:geolocation
    navigator.geolocation.getCurrentPosition((position)=>{
      //成功的回調
    },(error)=>{
      //錯誤的回調
    },{
      enableHighAccuracy: true, //儘量使用最準確的位置信息
      timeout: 5000,  //等待位置信息的最長時間
      maximumAge: 25000 //上一次取得座標信息的有效時間,時間到則從新獲取
    });
    
    //跟蹤監控
    let watchId = navigator.geolocation.watchPosition(position)=>{
      //成功的回調
    },(error)=>{
      //錯誤的回調
    });
    
    clearWatch(watchId); //關閉跟蹤
    
    瀏覽器中安裝的插件信息:plugins
    //IE瀏覽器無效
    function hasPlugin(name){
      return Array.from(navigator.plugins).some(item => item.name.toLowerCase().includes(name.toLowerCase()) )
    }
    hasPlugin("Flash");
    //IE瀏覽器
    function hasIEPlugin(name){
      try{
        new ActiveXObject(name);
        return true;
      }catch(ex){
        return false;
      }
    }
    hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
    
    cookie是否啓用:cookieEnabled
    瀏覽器所在的系統平臺:platform
    用戶代理:userAgent(可用於判斷瀏覽器引擎、版本、終端等)
    
    //簡易的瀏覽器類型判斷
    function browserType(){ //判斷瀏覽器類型
      let userAgent = navigator.userAgent;
      let type;
      switch(userAgent){
        case userAgent.includes("MSIE"):
          type = "IE";
          break;
        case userAgent.includes("Firefox"):
          type = "Firefox";
          break;
        case userAgent.includes("Chrome"):
          type = "Chrome";
          break;
        case userAgent.includes("Opera"):
          type = "Opera";
          break;
        case userAgent.includes("Safari"):
          type = "Safari";
          break;
        case userAgent.includes("Netscape"):
          type = "Netscape";
          break;
        default:
          console.log(userAgent);
          break;
      }
      return type;
    }
  8. history
    頁面前進:history.forward(); history.go(1);
    頁面後退:history.back(); history.go(-1);
    跳轉至可能存在的最近某個頁面(不存在則什麼都不作):history.go("...");
    歷史記錄數量:history.length(hash改變會使歷史記錄增長)
  9. 系統對話框node

    alert(val); //警告窗
    confirm(val); //確認窗,選擇OK,則返回true
    prompt(val,""); //輸入窗,選擇OK,則返回輸入框內容,不然返回null
  10. 數據存儲
    cookie:信息越大,對服務器的請求時間越長,故瀏覽器對其大小有限制,總量不到4Kes6

    //建立cookie
    function setCookie(name, value, expires, path, domain, secure) {
      var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);//防止中文亂碼,因此須要編碼
      (expires instanceof Date) && (cookieText += '; expires=' + expires); //有效期
      path && (cookieText += '; path=' + path); //設置域的路徑
      domain && (cookieText += '; domain=' + domain); //設置哪一個域的請求中都會包含該cookie信息,默認爲設置cookie的域
      secure && (cookieText += '; secure'); //只有在使用SSL鏈接的時候才發送到服務器
      document.cookie = cookieText;
    }
    
    //獲取cookie
    function getCookie(name) {
      var cookieName = encodeURIComponent(name) + '=';
      var cookieStart = document.cookie.indexOf(cookieName);
      var cookieValue = null;
      if (cookieStart > -1) {
        var cookieEnd = document.cookie.indexOf(';', cookieStart);
        if (cookieEnd == -1) {
          cookieEnd = document.cookie.length;
        }
        cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
      }
      return cookieValue;
    }
    
    //刪除cookie
    function unsetCookie(name) {
      document.cookie = name + "= ; expires=" + new Date(0);
    }

    localStorage:本地存儲,容量5M左右,值類型限定爲string類型,localStorage本質上是對字符串的讀取,若是存儲內容多的話會消耗內存空間,會致使頁面變卡,另外在部分瀏覽器隱私模式下不可讀取。
    sessionStorage:會話存儲(刷新頁面依舊存在),與localStorage在持久上不一樣外,其他一致。
    indexedDB:儲存空間很多於250M,沒有上限,異步設計,支持二進制儲存(ArrayBuffer對象和Blob對象)
    localforagejs庫,異步操做(自動加載最佳驅動程序,從IndexedDBlocalStorageajax

    //存儲
    localforage.setItem('key', 'value');
    
    localforage.setItem('key', 'value').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    localforage.setItem('key', 'value').then(()=>{
      return localforage.getItem('key');
    }).then(val=>{
      console.log(val);
    }).catch(err=>{
      console.log(err);
    });
    
    //獲取
    localforage.getItem('key').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    //刪除
    localforage.removeItem('key');
    
    localforage.removeItem('key').then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
    
    //清空
    localforage.clear();
    
    localforage.clear().then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    })
    
    //遍歷
    localforage.iterate((value, key)=>{
      console.log(key,value);
    }).then(()=>{
      ...
    }).catch(err=>{
      console.log(err);
    });
  11. DOMjson

    //querySelector選擇器,返回匹配的一個元素
    let parentElement = document.querySelector(".container");
    //建立元素
    let element = document.createElement("button");
    //設置元素的屬性
    element.setAttribute("onclick", `javascript:alert('click the span!');`);  
    //設置內容,innerText有兼容性問題,採用innerHTML較爲方便
    element.innerHTML = "建立元素添加的元素"; 
    //設置內聯樣式
    element.style.color = "blue";
    //在容器中末尾加入元素
    parentElement.appendChild(element);
    
    //添加元素的另外一種方式,該方式適合一次性建立多節點
    let elementHtml = `<button style="color:blue" onclick="javascript:alert('click the span!');">innerHTML方式添加的元素</button>`
    parentElement.innerHTML += elementHtml;
    
    //元素的克隆.cloneNode(true),父節點.parentNode,首個子節點.firstChild、下一個兄弟節點.nextElementSibling,加入到某個元素的前面refNode.parentNode.insertBefore(newNode,refNode)
    parentElement.insertBefore(parentElement.parentNode.cloneNode(true), parentElement.firstChild.nextElementSibling);//克隆一份parentElement的父節點,並將其放在parentElement的第一個子元素的下一個元素的前面
    
    let newElement = element.cloneNode(true);
    newElement.innerHTML = "newElement";
    
    //容器的最後一個子元素.lastChild,上一個兄弟節點.previousElementSibling,替換元素refNode.parentNode.insertBefore(newNode,refNode)
    parentElement.replaceChild(newElement, parentElement.lastChild.previousElementSibling);//替換parentElement最後一個子元素的上一個元素
    
    //querySelectorAll選擇器返回NodeList
    let firstContainer = document.querySelectorAll(".container")[0];
    
    //刪除元素node.parentNode.removeChild(node),元素子節點.children
    firstContainer.removeChild(firstContainer.children[0]);//刪除firstContainer這個元素的第一個子元素
    
    //動態添加樣式規則
    document.querySelector("head").innerHTML += `<style>.container{ height: 800px; background: red; }</style>`
    
    //移動滾動條至firstContainer這個元素可見,true或不傳表示元素頂端對齊,false表示底端在可視區域中間
    firstContainer.scrollIntoView(true);
    
    //獲取元素的真正樣式 window.getComputedStyle(element)
    console.log(window.getComputedStyle(firstContainer)) //獲取元素的真正樣式
    console.log(firstContainer.style); //獲取元素的內聯樣式
    
    //獲取元素的尺寸及相對於瀏覽器可視窗口的位置(非文檔,故頁面發生滾動會改變).getBoundingClientRect(),在計算座標使用時可用clientX配合getBoundingClientRect().left
    console.log(firstContainer.getBoundingClientRect());
  12. 事件流
    事件流過程:捕獲過程、目標、冒泡過程
    事件捕獲:從大到小,極少使用
    事件冒泡:從小到大,經常使用,雖然各瀏覽器有些差別
    阻止冒泡:e.stopPropagation(),IE9前使用e.cancelBubble=true
    阻止默認行爲:e.preventDefault(),IE9前使用e.returnValue=false
    默認行爲:如表單按鈕的提交,<a>標籤的跳轉等
    事件委託:利用事件冒泡,監聽頂級的DOM(事件處理程序數量關係到頁面的總體運行性能)
  13. 頁面事件
    pageshow事件:頁面顯示時觸發,事件目標爲document,但必須將其事件處理程序添加到window,參數爲event
    pagehide事件:頁面卸載時觸發,事件目標爲document,但必須將其事件處理程序添加到window,參數爲event
    haschange事件:URL的參數列表發生變化時觸發,但必須將其事件處理程序添加到window,參數爲event
    visibilitychange事件:綁定在document上,當頁面最小化或切換瀏覽器標籤等可見狀態改變觸發,documen.hidden可查看頁面可見度狀態canvas

    document.addEventListener('visibilitychange',function(){
      console.log(document.hidden);
    })
  14. 表單事件
    默認行爲:表單中的最後一個按鈕會自動提交表單
    form.submit()主動提交表單
    form.reset()重置表單
    form.checkValidity()表單驗證配合require和pattern使用
    noValidate屬性禁用表單驗證
    過濾輸入,屏蔽某些詞的默認行爲:監聽keypress事件,e.preventDefault();
    富文本編輯的實現:
    iframe實現,空文檔的designMode設置爲ongetSeclection事件獲取具體信息;
    ②設置contenteditable屬性實現,經過document.execCommand()實現富文本操做,如document.execCommand("blod", false, null);實現粗體文本。
  15. 鼠標事件
    雙擊事件順序:mousedownmouseupclickmousedownmouseupclickdblclick
    移入容器事件順序過程:mouseover(在不一樣元素間觸發)、mouseentermousemovemouseout(在不一樣元素間觸發)、mouseleave
    右鍵點擊事件:contextmenu(H5事件)
    位置信息:
      clientX(鼠標相對於瀏覽器窗口可視區域的X座標)
      offsetX(鼠標相對於事件源元素的X座標,存在兼容性問題)
      screenX(鼠標相對於用戶顯示器屏幕左上角的X座標)
      pageX(鼠標相對於文檔區域的X座標,存在兼容性問題)
    event對象屬性:
      type(事件類型)
      detail(點擊次數)
      target(事件源元素)
      path(數組,冒泡的路徑)
  16. 拖放事件
    相關事件:dragstart、drag、dragend、dragenter、dragover、dragleave、drop數組

    <section ondrop="drop(event)" ondragover="dragover(event)">投放目標</section>
    <div id="dragObj" src="xxx" draggable="true" ondragstart="drag(event)">被拖拽的物體</div>
    
    dragover(e){
      e.preventDefault();
    }
    drag(e){
      e.dataTransfer.setData("id",e.target.id);
    }
    drop(e){
      e.preventDefault();
      let data = e.dataTransfer.getData("id");
      e.target.appendChild(document.getElementById(data));
    }
  17. 觸摸與手勢事件
    移動端點擊事件順序:touchstarttouchendmouseovermouseentermousemovemousedownmouseupclick
    touchmove事件:須要阻止默認行爲以防止屏幕滾動
    touchcancel事件:當系統中止跟蹤觸摸時觸發
    gesturestart事件:當一個手指已經按在屏幕上而另外一個手指又觸摸時觸發
    gesturechange事件:當觸摸屏幕的任何一個手指的位置發生變化時改變
    gestureend事件:當任何一個手指從屏幕上面移開時觸發
    觸摸事件特有的event對象屬性:
      touches(表示當前跟蹤的觸摸操做的Touch對象的數組)
      targetTouchs(特定於事件目標的Touch對象的數組)
      changeTouches(上次觸摸以來發生了什麼改變的Touch對象的數組)
      rotation(手勢變化引發的旋轉角度,從0開始,順正逆負)
      scal(手指間的距離變化,從1開始,與距離呈正相關)
  18. 模擬事件
    UIEvents UI事件
    MouseEvents 鼠標事件
    MutationEvents DOM變更事件
    HTMLEvents HTML事件瀏覽器

    模擬鼠標點擊事件:
    1.建立鼠標事件的event對象
    let event = document.createEvent("MouseEvents");
    2.設置觸發的參數 //可簡寫,如event.initMouseEvent('click');
    event.initMouseEvent(事件類型,...event對象其餘參數);
    /*參數順序:type、bubbles(是否冒泡)、cancelable(事件是否可取消)、view(document.defaultView)、detail、screenX、screenY、clientX、clientY、ctrlKey(是否按下ctrl)、altKey(是否按下alt)、shiftKey(是否按下shiftKey)、metaKey(是否按下metaKey)、button(表示按下哪一個鼠標鍵)、relatedTarget(事件相關的對象,用於模擬mouseover/mouseout)*/
    3.觸發事件
    document.getElementById('btn').dispatchEvent(event);
  19. 媒體元素
    音頻播放器:audio
    視頻播放器:video
    經過play()pause()可手工控制媒體文件的播放和暫停,ended事件當播放結束時觸發
  20. 繪圖技術
    canvas:2D繪圖,可進行圖片與圖像的互轉,經過變換和合成繪製複雜圖像

    //獲取canvas內容生成的URI
    let imgURI = canvas.toDataURL("image/png");
    let img = document.createElement("img");
    img.src = imgURI;
    document.body.appendChild(img);

    svg:支持事件驅動,經過foreignObject可實現svg和普通HTML元素的融合
    WebGL:3D繪圖,非W3C標準

  21. ajax
    Asynchronous Javascript And XML,即異步JavaScript和XML,是一種建立交互式網頁應用的網頁開發技術。

    //封裝ajax
    function ajax(obj) {
      var xhr = new XMLHttpRequest(); //建立XMLHttpRequest實例
      obj.url = obj.url + '?rand=' + Math.random(); //爲url加時間戳
      if(obj.method === 'get') obj.url += '&' + obj.data;
      if(obj.async) xhr.onreadystatechange = ()=>{ (xhr.readyState == 4) && callback(); } //異步請求當readyState == 4才執行回調
      xhr.open(obj.method, obj.url, obj.async); //發送請求
      if(obj.method === 'post'){
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(obj.data); 
      }else{
        xhr.send(null);
      }
      if(!obj.async) callback(); //同步請求
      function callback() {
        if(xhr.status == 200){ obj.success(xhr.responseText); } //回調傳遞參數
        else{ console.log('獲取數據錯誤!錯誤代號:' + xhr.status + ',錯誤信息:' + xhr.statusText); }
      }
    }
    
    ajax({
      method : 'post/get',
      url : '...',
      data : "",
      success : (res)=>{
        console.log(res);
      },
      async : true
    });
  22. get與post請求
    get請求:從指定的資源請求數據,數據量和類型有限制(由於數據放在請求頭中,瀏覽器對其長度有限制),會被緩存,且數據在url上可見,致使安全性相對低點。
    post請求:向指定的資源提交被處理的數據,數據量和類型沒限制,不主動緩存,頁面刷新數據會被從新提交。
    底層分析:對於get請求,瀏覽器會把http headerdata一併發送出去,服務器響應200(返回數據),整個過程產生一個TCP數據包;對於post請求,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據),整個過程產生兩個TCP數據包,致使時間消耗,網絡環境暢通狀況下可無視。
  23. File API

    let reader = new FileReader();
    reader.readAsText(file,encoding); //以純文本的形式讀取文件,讀取到的文本保存在result屬性中
    //reader.readAsDataURL(file); //讀取文件以數據URI的形式保存在result屬性中
    //reader.readAsBinaryString(file); //讀取文件並將一個字符串保存在result屬性中,字符串中的每一個字符表示一字節
    //reader.readAsArrayBuffer(file); //讀取文件並將一個包含文件內容的ArrayBuffer保存在result屬性中
    reader.progress = (event)=>{
      if(event.lengthComputable){
        console.log(event.loaded + '/' + event.total);
      }
    }
    reader.onerror = ()=>{
      console.log(reader.error.code);
    }
    reader.onload = function(){
      console.log(reader.result);
    }
  24. 對象防篡改

    Object.preventExtensions(obj);  //對象不可拓展,禁止添加屬性或方法
    Object.seal(obj); //密封對象,不可刪除屬性和方法
    Object.freeze(obj); //凍結對象,不可拓展、且密封、不可編輯
  25. String、JSON、Object相互轉化

    //js對象轉JSON
    function jsToJSON(obj){
      let objFnToStr = fnToStr(obj);
      return JSON.stringify(objFnToStr);
    }
    
    //字符串轉JSON
    function strToJSON(str){
      let obj = eval('('+str+')');
      return jsToJSON(obj);
    }
    
    //JSON轉js對象
    function JSONToJs(json){
      let obj = JSON.parse(json);
      return strToFn(obj);
    }
    
    //將js對象中的函數字符串解析爲函數
    function strToFn(obj){
      var o = obj instanceof Array ? [] : {};
      for(var k in obj) {
        switch(typeof(obj[k])){
          case 'object':
            o[k] = obj[k] ? strToFn(obj[k]) : null;
            break;
          case 'string':
            o[k] = obj[k].match(/^\s*(function\s*\(.*\)\s*)|(\(.*\)\s*\=>\s*)/) ? eval('('+obj[k]+')') : obj[k];
            break;
          default:
            o[k] = obj[k];
            break;
        }
      }
      return o;
    }
    
    //將js對象中的函數類型轉爲字符串
    function fnToStr(obj){
      var o = obj instanceof Array ? [] : {};
      for(var k in obj) {
        switch(typeof(obj[k])){
          case 'object':
            o[k] = obj[k] ? fnToStr(obj[k]) : null;
            break;
          case 'function':
            o[k] = obj[k] + '';
            break;
          default:
            o[k] = obj[k];
            break;
        }
      }
      return o;
    }
  26. 定時器

    //延遲調用
    let timeId = setTimeout(fn,time);
    clearTimeout(timeId);
    
    //間歇調用
    let timeId = setInterval(fn,time);
    clearInterval(timeId);
    
    //定時器中的定時器
    setTimeout(function(){
      //...
      setTimeout(arguments.callee, interval);
    })
    
    //沉睡排序法
    [1,5,2,4,100,3].forEach(n=>{
      setTimeout(()=>{ console.log(n) }, n);
    })
  27. html與文本的轉換

    //字符串轉html字符串,參數:html傳入的字符串,type是否返回標籤結構,默認只返回內容,escape表示是否須要轉義
    function escapeHtml(html,type,escape){ //type:content/html,escape:轉義/不轉義
      let objE = document.createElement("div");
      objE.innerHTML = html;
      type 
        ? (escape 
          ? (html.includes('&') ? (objE.innerText = html) : (objE.innerText = new Option(html).innerHTML)) 
          : (html.includes('<') && (objE.innerText = html)))
        : (objE.innerHTML = objE.innerText);
      return objE.innerText;
    }
  28. 錯誤處理

    //監聽除 try catch 捕捉的錯誤
    window.onerror = (...error)=>{
      window.open("http://stackoverflow.com/search?q=[js] + "+error[0]);
    }
    
    //強制報錯
    var err = new Error("錯誤信息");
    console.error(err); //單純日誌輸出,不影響代碼執行
    throw err; //顯示報錯,致使後面代碼不解析
相關文章
相關標籤/搜索