<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          10個JavaScript常見BUG及修復方法

          時間:?2017-11-15閱讀:?965標簽:?bug

          譯者按: JavaScript語言設計太靈活,用起來不免要多加小心掉進坑里面。

          原文: Top 10 bugs and their bug fixing 譯者: Fundebug

          為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。

          如今網站幾乎100%使用JavaScript。JavaScript看上去是一門十分簡單的語言,然而事實并不如此。它有很多容易被弄錯的細節,一不注意就導致BUG。


          1. 錯誤的對this進行引用

          在閉包或則回調中,this關鍵字的作用域很容易弄錯。舉個例子:

          Game.prototype.restart = function () {
            this.clearLocalStorage();
            this.timer = setTimeout(function() {
              this.clearBoard();    // 此處this指的是?
            }, 0);
          };


          如果執行上面的代碼,我們會看到報錯:

          Uncaught TypeError: undefined is not a function


          出錯的原因在于:當你調用setTimeout函數,你實際上調用的是window.setTimeout()。在setTimeout中傳入的匿名函數是在window這個對象環境下,所以this是指向window,但是window并沒有clearBoard方法。

          如何解決呢?定義新的變量引用指向Game對象的this,然后就可以使用啦。

          Game.prototype.restart = function () {
            this.clearLocalStorage();
            var self = this;   // 將this指向的對象綁定到self
            this.timer = setTimeout(function(){
              self.clearBoard();
            }, 0);
          };


          或則使用bind()函數:

          Game.prototype.restart = function () {
            this.clearLocalStorage();
            this.timer = setTimeout(this.reset.bind(this), 0);  // bind to 'this'
          };
          Game.prototype.reset = function(){
              this.clearBoard();    // 此處this的引用正確
          };


          2. 和塊作用域(block scope)有關的BUG

          在大多數程序語言中,每一個函數塊都有一個獨立的新的作用域,但是在JavaScript中并不是。例如:

          for (var i = 0; i < 10; i++) {
            /* ... */
          }
          console.log(i);  // 會輸出什么呢?


          通常在這種情況下,調用console.log()會輸出undefined或則報錯。不過呢,這里會輸出10。在JavaScript中,即使for循環已經結束,變量i依然存在,并且記錄最后的值。有些開發者會忘記這一點,然后導致許多bug。我們可以使用let而不是for來杜絕這一問題。


          3. 內存泄漏

          你需要監控內存使用量,因為泄露很難避免。內存泄露可能由于引用不存在的對象或則循環引用導致。

          如何避免:關注對象的可訪問性(reachability)。

          可訪問的對象:現有的call stack任何位置可以訪問的對象

          全局對象:當一個對象可以通過引用訪問到,那么會在內存中保存。瀏覽器的垃圾回收器僅僅會把那些不可訪問的對象回收。


          4. 混淆的相等判斷

          JavaScript自動將所有在布爾環境下的變量類型轉換為布爾類型,但是可能導致bug。舉例:

          // 所有都是true
          console.log(false == '0');
          console.log(null == undefined);
          console.log(" \t\r\n" == 0);
          console.log('' == 0);
          // 注意:下面兩個也是
          if ({}) // …
          if ([]) // …


          {}和[]都是對象,他們都會被轉換為true。為了防止bug出現,推薦使用===和!==來做比較,因為不會隱式做類型轉換。


          5. 低效的DOM操作

          在JavaScript中,你可以輕松操作DOM(添加、修改和刪除),但是開發者往往很低效地去操作。這會導致bug出現,因為這些操作非常耗費計算資源。為了解決這個問題,推薦使用文檔碎片(Document Fragment),如果你需要操作多個DOM元素。

          廣告: 你的線上代碼真的沒有BUG嗎?歡迎免費使用Fundebug!我們可以幫助您第一時間發現BUG!


          6. 在for循環中錯誤的定義函數

          舉例:

          var elements = document.getElementsByTagName('input');
          var n = elements.length;    // 假設我們有10個元素
          for (var i = 0; i < n; i++) {
              elements[i].onclick = function() {
                  console.log("元素編號#" + i);
              };
          }


          如果我們有10個元素,那么點擊任何一個元素都會顯示“元素編號#10”!因為在onclick被調用的時候,for循環已經結束,因此所有的i都是10。

          解法:

          var elements = document.getElementsByTagName('input');
          var n = elements.length;    // 假設有10個元素
          var makeHandler = function(num) {  // outer function
               return function() {   // inner function
                   console.log("元素編號##" + num);
               };
          };
          for (var i = 0; i < n; i++) {
              elements[i].onclick = makeHandler(i+1);
          }


          makeHandler在for循環執行的時候立即被調用,獲取到當前的值i+1,并且存儲在變量num中。makeHandler返回一個函數使用num變量,該函數被綁定到元素的點擊事件。


          7. 通過原型錯誤地繼承

          開發者如果沒能正確理解繼承的原理,那么就可能寫出有bug的代碼:

          BaseObject = function(name) {
              if(typeof name !== "undefined") {
                  this.name = name;
              } else {
                  this.name = 'default'
              }
          };
          var firstObj = new BaseObject();
          var secondObj = new BaseObject('unique');
          console.log(firstObj.name);  // -> 輸出'default'
          console.log(secondObj.name); // -> 輸出'unique'


          但是,如果我們做如下操作:

          delete secondObj.name;


          那么:

          console.log(secondObj.name); // -> 輸出'undefined'


          而我們實際上想要的結果是打印默認的name。

          BaseObject = function (name) {
              if(typeof name !== "undefined") {
                  this.name = name;
              }
          };
          BaseObject.prototype.name = 'default';


          每一個BaseObject都繼承name屬性,并且默認值為default。此時如果secondObj的name屬性被刪除掉,通過原型鏈查找會返回正確的默認值。

          var thirdObj = new BaseObject('unique');
          console.log(thirdObj.name);  // -> 輸出'unique'
          delete thirdObj.name;
          console.log(thirdObj.name);  // -> 輸出'default'


          8. 實例方法中的無效引用

          我們來實現一個簡單的構造函數用來創建對象:

          var MyObject = function() {}
          MyObject.prototype.whoAmI = function() {
              console.log(this === window ? "window" : "MyObj");
          };
          var obj = new MyObject();


          為了使用方便,我們定義變量whoAmI來引用obj.whoAmI:

          var whoAmI = obj.whoAmI;


          打印出來看看:

          console.log(whoAmI);


          控制臺會輸出:

          function () {
              console.log(this === window ? "window" : "MyObj");
          }


          現在我們來對比一下兩者調用的區別:

          obj.whoAmI();  // 輸出"MyObj" (和期望一致)
          whoAmI();      // 輸出"window" (竟然輸出了window)


          當我們把obj.whoAmI賦值給whoAmI的時候,這個新的變量whoAmI是定義在全局下,因此this指向全局的window,而不是MyObj。如果我們真的要獲取對MyObj的函數的引用,需要在其作用域下。

          var MyObject = function() {}
          MyObject.prototype.whoAmI = function() {
              console.log(this === window ? "window" : "MyObj");
          };
          var obj = new MyObject();
          obj.w = obj.whoAmI;   // 任然在obj的作用域
          obj.whoAmI();  // 輸出"MyObj"
          obj.w();       // 輸出"MyObj"


          9. setTimeout/setInterval函數第一個參數誤用字符串

          如果你將一個字符串作為setTimeout/setTimeInterval,它會被傳給函數構造函數并構建一個新的函數。該操作流程很慢而且低效,并導致bug出現。

          var hello = function(){
            console.log("hello, fundebug !");
          }
          setTimeout("hello", 1000);


          一個好的替代方法就是傳入函數作為參數:

          setInterval(logTime, 1000);   // 將logTime函數傳入
          setTimeout(function() {       // 傳入一個匿名函數
              logMessage(msgValue);     
            }, 1000);


          10. 未能成功使用strict mode

          使用strict model會增加很多限制條件來加強安全和防止某些錯誤的出現,如果不使用strict mode,你就相當于少了一個得力的助手幫你避免錯誤:

          更加容易debug
          避免不小心定義了不該定義的全局變量
          避免this隱式轉換
          避免屬性名字或則參數值的重復使用
          eval()更加安全
          無效地使用delete會自動拋出錯誤


          站長推薦

          1.阿里云: 本站目前使用的是阿里云主機,安全/可靠/穩定。點擊領取2000元代金券、了解最新阿里云產品的各種優惠活動點擊進入

          2.騰訊云: 提供云服務器、云數據庫、云存儲、視頻與CDN、域名等服務。騰訊云各類產品的最新活動,優惠券領取點擊進入

          3.廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入

          鏈接: http://www.modern-decoration.com.cn/article/detial/112

          前端頁面禁止調試debugger方法匯總

          打開控制臺直接跳轉頁面;打開控制臺,頁面內容顯示:檢測到非法調試,請關閉后刷新重試!反調試函數,參數:開關,執行代碼

          Vue中你可能認為是bug的情況原來是這樣的

          我們知道Vue框架劇本雙向數據綁定功能,在我們使用方便的同時,還有一些細節問題我們并不知道,接下來一起探討一些吧.Vue做數據劫持是基于Object.defineProperty的,但是他只能做set和get,而無法監視到屬性的增加或者減少

          css重點知識和bug解決方法

          圖片向下撐大3像素問題;如何實現一張未知寬高的圖片在一個盒子里面做水平垂直居中?元素的類型分類哪幾種?各自都有什么特點?如何實現一個元素消失和出現?單行文本溢出顯示省略號怎么實現?

          ios 鍵盤彈起bug,出現的問題,光標穿透,頁面無法點擊

          有時候使用ios輸入鍵盤以后,直接點擊頁面按鈕會出現事件無效。解決方法:1、 輸入框輸入后點擊提交按鈕后,彈窗會發現光標穿透問題

          如何阻止頁面不斷debugger?

          一次扒某網站的前端代碼,打開控制臺要看Network,結果發現他們頁面一打開控制臺就不斷的debugger,100ms一次,很影響看頁面內容。而對應的操作是在Chrome控制臺的Source Tab頁點擊Deactivate breakpoints按鈕或者按下Ctrl + f8

          移動端常見bug

          當你點擊一個鏈接或者通過Javascript定義的可點擊元素的時候,它就會出現一個半透明的灰色背景。根本原因是-webkit-tap-highlight-color,這個屬性是用于設定元素在移動設備(如Adnroid、iOS)上被觸發點擊事件時

          jquery綁定點擊事件動畫BUG

          jq中的animate()方法所實現的動畫在綁定事件的同時會產生各種類型的BUG,在事件選擇的時候我會盡可能的使用mouseenter和mouseleave來避免,mouseover和mouseout所產生的事件冒泡。

          程序員如何減少開發中的 Bug?

          周會上同事拋出了一個問題,程序員如何減少開發中的 Bug?很有意思的一個話題,本篇文章我們來進行探討與總結。愛因斯坦曾經說過:「如果給我一個小時解答一道決定我生死的問題,我會花55分鐘來弄清楚這道題到底是在問什么

          Web開發人者的十大Bug跟蹤工具

          有許多可視化的 Bug 跟蹤工具,通常可以根據特性集、集成和定價進行分類。選擇一個 Bug 跟蹤工具時,需要整體考慮團隊的規模和需求。對于很多團隊來說,項目管理并不是必需的,因此對 Bug 跟蹤工具的真正需求變成了一個強大的解決方案提供者

          不能精準定位bug?可能是你沒get到這幾個打印日志的訣竅!

          當你遇到問題的時候,只能通過debug功能來確定問題,你應該考慮打日志,良好的系統,是可以通過日志進行問題定位的。當你碰到if…else 或者 switch這樣的分支時,要在分支的首行打印日志,用來確定進入了哪個分支

          內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權或違規,請與小編聯系!情況屬實本人將予以刪除!

          文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

          小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全運營推廣

          国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网