記一次尋找Bug的經歷-從新理解javascript原型和程序員瓶頸

記一次尋找Bug的經歷

今天下午的時候,同事說發現了一個問題.Ext4作好頁面,從新單擊菜單動態加載一次,樹就消失了. 因而,我幫忙看了一下,一開始沒認爲是什麼大問題.可是越調發現越不對.到快下班的時候,沒有什麼思路.因而再也不隨便看了.好好Debug一下Ext源代碼來找問題.到晚上七點半.終於問題搞定了.此次Debug的過程過後想一想真是過癮.由於不只僅是解決了一個bug.javascript

最重要的是對javascript更進一步有所瞭解了.java

晚上回家,總以爲得記下來,不是記錄技術方面的收穫,由於知識點變來變去就那麼點東西.都是之前就知道的東西,只不過變了一個樣子就不會了.我想寫寫此次調試過程當中的本身的一些猜想還有過後對於程序員的見解.程序員

首先描述一下問題.app

Ext實現簡單的動態加載菜單.函數

點擊菜單,在TabPanel上加載一個Tab窗體,窗體裏面有一個tree控件.this

在此輸入圖片描述

第一次加載沒問題,可是再點擊一次的話prototype

對,樹就神奇的消失了.debug

在此輸入圖片描述

代碼的話:設計

<!-- lang: js -->
//首先是動態加載菜單的代碼段
    listeners: {
    itemclick: function (_this, record, item, index, e, eOpts) {
        if (record.data.leaf) {
            var MainContiner = Ext.getCmp("MainContiner");
            var action = Ext.create(record.raw.action.package, record.raw.action);
            if (!MainContiner.child(action) ||
                    record.raw.action.package == "app.actionPanel.ActionPanel")
            {
                MainContiner.add(action);
            }
            MainContiner.setActiveTab(action);
        }
     }
     }

<!-- lang: js -->
//而後是窗體的定義片斷的構造函數
     constructor: function () {
    var marktypeTree = Ext.create("app.mark.markTree",{
        callback:function(data){
            if (data != null) {
                Ext.getCmp("MainContiner").child("#staffTypeID").child("#panelGridId").treeNode.push(data)
                          Ext.getCmp("MainContiner").child("#staffTypeID").child("#panelGridId").child("#markTypeGrid").store.reload({
                    params: {
                        _id: data
                    }
                })
            }
        }
    });
    this.items[0].items.push(marktypeTree);
    this.callParent(arguments);
    var a=0;
},

第一眼我看到這個問題,先懷疑的是樹控件被釋放掉了.或者樹控件被重寫了.可是檢查了一遍代碼,發現沒有這個問題.而後debug看兩次單擊,窗體到底有什麼變化.發現點擊兩次,panel下面會加入兩顆樹控件.調試

並且單擊次數越多,加入的數量越多.立馬就不明白了.按理說第二次單擊窗體判斷同一個窗體後,不會再加入到tab中.可是樹怎麼就進去了呢.

而後調試了很長時間,忽然有了一個想法...因而寫了一個小例子.........

<!-- lang: js -->
function A(){
}
function B(){
    this.b=1;
    this.arr=[];
    this.obj={};
}

A.prototype = new B();

var a = new A();

a.b//這個變量是能夠經過圓形查找查到的.

a.c=1;

a.c//這個c變量在a對象下面,

a.arr.push(1);//這個地方就有意思了.
//a.arr 會引用到原型裏面.push一下後.變量就被增長到 原型對象裏面了.
//對了.這個地方就是js裏面的引用.
//對象也符合這個引用.
//換句話說
var a2 = new A();
a2.arr.length;//這裏length是1.由於原型域是共享的域.

這裏反思一下.一直以來,把javascript當作面向對象去學的話.原型會類比繼承.可是javascript畢竟不是面向對象的.因此形成這個問題給疏忽了.若是從原型角度來考慮.這就是基本知識點.

問題改過來了.我想到了不少別的問題.

首先對於javascript.再強調一次.把js當作面嚮對象語言去學是種耍流氓的行爲.遲早碰壁.javascript是原型函數式語言. 我能夠操做原型域實現面向對象實現不了有意思的功能.若是是面向對象的思惟方式,上面的問題就是Bug.可是這不是.這是一個頗有趣的探索.

其次,關於如何解決bug的問題.感受跳錯須要一種迴歸原點的能力.就是可以把目前的問題回退到問題最初的能力. 不少人調試程序.編譯器報錯了,就粘貼出來錯誤百度.而後順着日後找錯.找不到就說這問題無法解決.或者就算找到了.大多經過增長代碼的方式去調試.各類條件一限定.不出錯了.可是你問爲何出錯啊?xx的問題....基本都是很表面的答案.

我以爲寫代碼,應該能站到設計者的角度去寫.你用Ext.就得站到Ext設計者角度去寫代碼.理解Ext代碼運行機制.一樣的bug.有太多的方式能夠解決.可是從Ext的運行機制上去考慮解決的方法就沒有那麼多了.

如何迴歸代碼設計的原點,經過非干預的手段來解決問題.我以爲這種理解能力.是一個程序員成長到必定程度會遇到的新的瓶頸.

相關文章
相關標籤/搜索