JavaScript 的那些坑

Ecmascript

  1. 大括號的位置

    function f() {
      return
      {
        h:'Hello World'
      }
    }
    console.log(f())  //undefined
    

    Javascript自動在return語句后面添加了分號結束該行,所以該函數(shù)返回的是undefined
    相當于執(zhí)行了下面的語句

    function f() {
      return ;
      {
        h:'Hello World'
      }
    }
    console.log(f())  //undefined
    
  2. 語句合并造成的坑

    function g() {
      var a = b = 0;
    }
    
    g()
    
    console.log(a)  //Type Error: a is not defined
    console.log(b)  // 0
    

    上面的語var a = b = 0, 你以為的解析為 var a = 0; var b = a; 實際上解析為
    b = 0; var a = b; 所以b是一個全局變量, 掛載到全局對象上, a是一個局部對象,在函數(shù)外部無法訪問.

  3. 變量提升

    • 局部變量提升, 只提升聲明
    if (!o) {
        var o = {a:1};
        console.log(o);
    }// 變量的聲明被提升
    // 實際上解析成這樣
    var o;
    if (!o) {
      o = {a:1};
      console.log(o)
    }
    
    • 下面的代碼會報 f is not a function
    if (false) {
      function f() {
        console.log("Hello World")
      }
    }
    f()  // 報錯
    
    • 變量提升和函數(shù)提升
    var myname = "";
    console.log(typeof myname) // string
    
    function myname() {}
    console.log(typeof myname)  //string
    
    • 不會被條件判斷所控制
    foo(); // TypeError: foo is not a function()
    var a = true;
    if (a) {
        function foo() {console.log("a")}
    } else {
        function foo() {console.log("b")}
    }
    
    // 這種情況下打印出 undefined
    console.log(typeof foo)
    var a = true;
    if (a) {
        function foo() {console.log("a")}
    } else {
        function foo() {console.log("b")}
    }
    
  4. 分號坑

    var a = 1
    (function() {
      console.log(a)
    })()
    

    以為會安全的打印a的值,實際上報錯,如果下一行的第一個字元(token)是下面這五個字符之一传藏,Javascript將不對上一行句尾添加分號:"("、"["、"/"、"+"和"-"。

  5. 內存泄漏的識別方法
    怎樣可以觀察到內存泄漏呢柳譬?

    經驗法則是,如果連續(xù)五次垃圾回收之后,內存占用一次比一次大济榨,就有內存泄漏。這就要求實時查看內存占用绿映。

  6. setTimeout與this

    //setTimeout中的函數(shù)所處在于全局作用域中擒滑,所以函數(shù)中使用this關鍵字時,這個this關鍵字指向的是全局對象(Window): 
    var Value1 = 200;
    var Value2 = 20;
    var myObj = {
        Value1 : 10,
        Value2 : 1,
        caleculatedIt: function(){
            setTimeout(function(){
                console.log(this.Value1 * this.Value2);
                
            }, 1000);
        }
    }
    myObj.caleculatedIt(); //4000
    
  7. typeof的坑

    • typeof 查看變量的類型
    typeof null //"object"
    typeof NaN  // "number"
    typeof eval // "function"
    
    // 判斷Class的類型: 
    ({}).toString.call(classA);
    
    • instanceof
      • 適合自定義對象
      • 也可以檢測原生對象, 但在iframe和window檢測失效
  8. NaN判斷

    • parseInt("abc") === NaN // NaN與任何值比較都為false, 即使NaN==NaN也是false

    • 正確的判斷方式

      var b = isNaN(parseInt(abc))
      
  9. 類型轉換

    • parseInt和Number

      var num = parseInt(str);  //會提取其中的數(shù)字
          //str="abc"           //NaN(not a number)
          //str = "abc 12 bc"   //NaN
          //str = "123px"       //123 從最左邊提取
      
      var num = Number("123");
      var num = Number("123abc"); //NaN, 比Number嚴格轉換
      
      
    • 隱式轉換 隱式轉換坑

      var a = 12, b = "12";
          alert(a==b) //返回true b字符串轉成數(shù)字, 但是typeof b仍然是string
      
      
      alert('12' - '7')  // 5  兩邊都轉成數(shù)字后計算
      alert('12' + '7')  // '127' 字符串串聯(lián)
      alert(12 + '7')  // '127' 數(shù)字轉字符串
      // 總結: 減法,乘法,除,取余,大于小于等操作都轉成Number類型
      
      
  10. 構造器中的this

    function c()
    {
        this.a = 37;
        return {a:38};
    }
    
    o= new c();
    console.log(o.a); //38 o為返回的對象 如果返回的是基本類型 那么就返回this
    
    
    function d()
    {
        this.e = 37;
        return {f:38};
    }
    o1 = new d()
    console.log(o1.e) // undefined   o1對象中只有f屬性 沒有e屬性
    
    
  11. 嚴格模式下, arguments跟蹤問題

    // 兩次都是1
    (function fn(a) {
      'use strict';
      console.log(arguments[0]);
      a = 2;
      console.log(arguments[0]);
    })(1);
    // 兩次打印的都是1, 如果實在非嚴格模式下, 打印的是1,2
    
  12. 實參和形參

    var add = function (a,b) {
      console.log(arguments.length);//3,表示實參長度
      console.log(arguments.callee.length);//2叉弦,表示形參長度
    };
    
    add(1,2,3);
    

JavaScript操作DOM的坑

  1. 獲取鼠標點擊的位置 (即鼠標點擊的位置距離document左上角的位置)

Firefox丐一,Chrome、Safari和IE9都是通過非標準事件的pageX和pageY屬性來獲取web頁面的鼠標位置的淹冰。

function mouseClick(event) {
    event = event || window.event;
    var x = 0, y = 0;
    if (event.pageX) {
        x = event.pageX;
        y = event.pageY;
    } else if(event.clientX){
        var scrollLeft, scrollTop
        if (document.documentElement.scrollLeft) {
            scrollLeft = document.documentElement.scrollLeft
            scrollTop = document.documentElement.scrollTop
        } else if (document.body.scrollLeft) {
            scrollLeft = document.body.scrollLeft
            scrollTop = document.body.scrollTop
        }
        x = event.clientX + scrollLeft
        y = event.clientY + scrollTop
    }
    
    return {
        x,
        y
    }
}
  • scrollLeft, scrollTop 為滾動軸卷起的左側距離和頂部距離, 即滑動軸滾動的距離
  • clientX, clientY 為鼠標點擊的位置距離瀏覽器可視區(qū)域左上邊角的距離, 與有無滾動軸無關
    image
  1. offsetLeft和style.left區(qū)別

    • style.left返回的是字符串库车,比如10px。而offsetLeft返回的是數(shù)值樱拴,比如數(shù)值10
    • style.left是可讀寫的柠衍,offsetLeft是只讀的
    • style.left的值需要事先定義(在樣式表中定義無效洋满,只能取到在html中定義的值),否則取到的值是空的
  2. getComputedStyle 和 elment.currentStyle

    • getComputedStyle(obj, false) 是支持w3c(FF12珍坊、chrome14牺勾、safari):在FF新版本中只需要第一個參數(shù),即操作對象阵漏,第二個參數(shù)寫“false”也是大家通用的寫法驻民,目的是為了兼容老版本的火狐瀏覽器。缺點:在標準瀏覽器中正常履怯,但在IE6/7/8中不支持
    • 在IE6,7,8中回还,并不支持getComputedStyle,IE提供了currentStyle屬性
    var oDiv=document.getElementById('div1');
    if(oDiv.currentStyle){ // IE6,7,8
        alert(oDiv.currentStyle.width);
    }else{// IE9+ FF Chrome Opera
        alert(getComputedStyle(oDiv).width);
    }
    
  3. 事件監(jiān)聽和默認時間, 冒泡處理

    • addListener|removeListener, preventDefault(), stopBubble(): IE9+ FF Chrome Opera w3c
    • attachEvent|detachEvent, returnValue=true, cancelBubblue=true, cancel: IE6,7,8
    function listenEvent(target,type,handler){
        if(target.addEventListener){//w3c
            target.addEventListener(type,handler,false);
        }else if(target.attachEvent){//IE
            type = "on" + type;
            target.attachEvent(type,handler);//IE
        }else{
            target["on" + type] = handler;
        }
    }
    
    //取消事件
    function cancelEvent(e){
        if(e.preventDefault){
            e.preventDefault();//w3c
        }else{
            e.returnValue = false;//IE
        }
    }
    //取消傳遞
    function cancelPropagation(e){
        if(e.stopPropagation){
            e.stopPropagation();//w3c
        }else{
            e.cancelBubble = true;//IE
        }
    }
    
  4. 獲取瀏覽器窗口尺寸

    function size(){
        var w = 0, h=0;
         // IE6, 7, 8
        if(!window.innerWidth){
            w = (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth);
    
            h = (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
        }
        // IE9+ FF Chrome Opera W3C 
        else{
            w = window.innerWidth;
            h = window.innerHeight;
        }
        return {width:w,height:h};
    }
    
    //實用的 JavaScript 方案(涵蓋所有瀏覽器):
    
    var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    
    var h=window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight;
    

    Document對象的body屬性對應HTML文檔的<body>標簽叹洲。
    Document對象的documentElement屬性則表示 HTML文檔的根節(jié)點柠硕。

  5. attributes屬性

    attributes 屬性返回該節(jié)點的屬性節(jié)點集合。

    document.getElementById('box').attributes//NamedNodeMap
    document.getElementById('box').attributes.length;//返回屬性節(jié)點個數(shù)
    document.getElementById('box').attributes[0]; //Attr运提,返回第一個屬性節(jié)點
    document.getElementById('box').attributes[0].nodeType; //2蝗柔,節(jié)點類型
    document.getElementById('box').attributes[0].nodeValue; //屬性值
    document.getElementById('box').attributes['id']; //Attr,返回屬性為 id 的節(jié)點
    document.getElementById('box').attributes.getNamedItem('id'); //Attr
    
    • setAttribute(attrName, value) 不建議使用設置class和style
      • setAttribute('class', 'container') for FF
      • setAttribute('className', 'conatainer') forIE, IE不認識class
    • getAtribute(attrName) 統(tǒng)一獲取自定義屬性
    • removeAttrite(attrName)
  6. 獲取目標對象

    //跨瀏覽器獲取目標對象
    function getTarget(ev){
        var ev = ev || window.event
        if(ev.target){ //w3c IE9+
            return ev.target;
        }else if(window.event.srcElement){//IE6, 7, 8
            return window.event.srcElement;
        }
    }
    
    target = event.target ?  event.target: event.srcElement;
    
  7. Node接口

    特性/方法 類型/返回類型 說明
    nodeName String 節(jié)點的名稱, 節(jié)點類型而定義
    nodeValue String 節(jié)點的值 文本節(jié)點返回文本
    nodeType Number 節(jié)點類型常量值 元素0 屬性1 文本2
    childNodes NodeList 所有子節(jié)點列表(包括元素節(jié)點和文本節(jié)點)
    firstNode Node childNodes列表中的第一個節(jié)點
    lastNode Node childNodes列表中的最后一個節(jié)點
    children NodeList 子節(jié)點列表中只返回元素節(jié)點
    previouSibling Node 上一同級節(jié)點
    nextSibling Node 下一同級節(jié)點
    hasChildNodes() Boolean 是否擁有子節(jié)點
    attributes NamedNodeMap 返回屬性NamedNodeMap
    appendChild(Node) Node 節(jié)點添加到childNodes末尾
    removeChild(Node) Node 從childNodes中刪除node
    replaceNode(new, old) Node 將childNodes中的old替換成new
    insertBefore Node 在已有子節(jié)點之前插入新子節(jié)點
    • 返回父節(jié)點: node.parentNode || node.parentElement (IE)
    • 返回子文本節(jié)點集合:node.textNodes
    • 節(jié)點信息
      • 是否包含某節(jié)點:node.contains()
      • 是否有子節(jié)點node.hasChildNodes()
    • 創(chuàng)建新節(jié)點
      • createDocumentFragment() -創(chuàng)建文檔碎片節(jié)點
      • createElement(tagname) -創(chuàng)建標簽名為tagname的元素
      • createTextNode(text) -創(chuàng)建包含文本text的文本節(jié)點
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末糙捺,一起剝皮案震驚了整個濱河市诫咱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洪灯,老刑警劉巖坎缭,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異签钩,居然都是意外死亡掏呼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門铅檩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憎夷,“玉大人,你說我怎么就攤上這事昧旨。” “怎么了兔沃?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵蒋得,是天一觀的道長。 經常有香客問我乒疏,道長额衙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮窍侧,結果婚禮上县踢,老公的妹妹穿的比我還像新娘。我一直安慰自己伟件,他們只是感情好硼啤,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锋爪,像睡著了一般丙曙。 火紅的嫁衣襯著肌膚如雪爸业。 梳的紋絲不亂的頭發(fā)上其骄,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音扯旷,去河邊找鬼拯爽。 笑死,一個胖子當著我的面吹牛钧忽,可吹牛的內容都是我干的毯炮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼耸黑,長吁一口氣:“原來是場噩夢啊……” “哼桃煎!你這毒婦竟也來了?” 一聲冷哼從身側響起大刊,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤为迈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缺菌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葫辐,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年伴郁,在試婚紗的時候發(fā)現(xiàn)自己被綠了耿战。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡焊傅,死狀恐怖剂陡,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情狐胎,我是刑警寧澤鸭栖,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站顽爹,受9級特大地震影響纤泵,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一捏题、第九天 我趴在偏房一處隱蔽的房頂上張望玻褪。 院中可真熱鬧,春花似錦公荧、人聲如沸带射。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窟社。三九已至,卻和暖如春绪钥,著一層夾襖步出監(jiān)牢的瞬間灿里,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工程腹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匣吊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓寸潦,卻偏偏與公主長得像色鸳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子见转,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容

  • 工廠模式類似于現(xiàn)實生活中的工廠可以產生大量相似的商品命雀,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式斩箫。簡單...
    舟漁行舟閱讀 7,723評論 2 17
  • 單例模式 適用場景:可能會在場景中使用到對象吏砂,但只有一個實例,加載時并不主動創(chuàng)建校焦,需要時才創(chuàng)建 最常見的單例模式赊抖,...
    Obeing閱讀 2,056評論 1 10
  • 轉載請聲明出處 博客原文 隨手翻閱以前的學習筆記,順便整理一下放在這里寨典,方便自己復習氛雪,也希望你有也有幫助吧 第一課...
    程序員poetry閱讀 12,645評論 13 94
  • 轉載請著名出處 GitHub-TYRMars 文章Github地址 JavaScript基礎知識剖析 01 01-...
    TYRMars閱讀 554評論 0 7
  • 1 天還沒亮嗎报亩?我從昏迷中睜開眼,但見頭頂?shù)臒艄獍讘K慘的井氢,我怕再也見不到太陽了吧弦追? 老公趴在床沿上,緊緊攥著我的手...
    有故事的牛魔王閱讀 626評論 5 4