美文网首页
JavaScript 的那些坑

JavaScript 的那些坑

作者: FConfidence | 来源:发表于2017-08-07 20:44 被阅读196次

    Ecmascript

    1. 大括号的位置

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

      Javascript自动在return语句后面添加了分号结束该行,所以该函数返回的是undefined
      相当于执行了下面的语句

      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是一个局部对象,在函数外部无法访问.

    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()  // 报错
      
      • 变量提升和函数提升
      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. 内存泄漏的识别方法
      怎样可以观察到内存泄漏呢?

      经验法则是,如果连续五次垃圾回收之后,内存占用一次比一次大,就有内存泄漏。这就要求实时查看内存占用。

    6. setTimeout与this

      //setTimeout中的函数所处在于全局作用域中,所以函数中使用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);  //会提取其中的数字
            //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字符串转成数字, 但是typeof b仍然是string
        
        
        alert('12' - '7')  // 5  两边都转成数字后计算
        alert('12' + '7')  // '127' 字符串串联
        alert(12 + '7')  // '127' 数字转字符串
        // 总结: 减法,乘法,除,取余,大于小于等操作都转成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 为鼠标点击的位置距离浏览器可视区域左上边角的距离, 与有无滚动轴无关 image
    1. offsetLeft和style.left区别

      • style.left返回的是字符串,比如10px。而offsetLeft返回的是数值,比如数值10
      • style.left是可读写的,offsetLeft是只读的
      • style.left的值需要事先定义(在样式表中定义无效,只能取到在html中定义的值),否则取到的值是空的
    2. getComputedStyle 和 elment.currentStyle

      • getComputedStyle(obj, false) 是支持w3c(FF12、chrome14、safari):在FF新版本中只需要第一个参数,即操作对象,第二个参数写“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. 事件监听和默认时间, 冒泡处理

      • 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文档的根节点。

    5. attributes属性

      attributes 属性返回该节点的属性节点集合。

      document.getElementById('box').attributes//NamedNodeMap
      document.getElementById('box').attributes.length;//返回属性节点个数
      document.getElementById('box').attributes[0]; //Attr,返回第一个属性节点
      document.getElementById('box').attributes[0].nodeType; //2,节点类型
      document.getElementById('box').attributes[0].nodeValue; //属性值
      document.getElementById('box').attributes['id']; //Attr,返回属性为 id 的节点
      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) 统一获取自定义属性
      • 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 节点的名称, 节点类型而定义
      nodeValue String 节点的值 文本节点返回文本
      nodeType Number 节点类型常量值 元素0 属性1 文本2
      childNodes NodeList 所有子节点列表(包括元素节点和文本节点)
      firstNode Node childNodes列表中的第一个节点
      lastNode Node childNodes列表中的最后一个节点
      children NodeList 子节点列表中只返回元素节点
      previouSibling Node 上一同级节点
      nextSibling Node 下一同级节点
      hasChildNodes() Boolean 是否拥有子节点
      attributes NamedNodeMap 返回属性NamedNodeMap
      appendChild(Node) Node 节点添加到childNodes末尾
      removeChild(Node) Node 从childNodes中删除node
      replaceNode(new, old) Node 将childNodes中的old替换成new
      insertBefore Node 在已有子节点之前插入新子节点
      • 返回父节点: node.parentNode || node.parentElement (IE)
      • 返回子文本节点集合:node.textNodes
      • 节点信息
        • 是否包含某节点:node.contains()
        • 是否有子节点node.hasChildNodes()
      • 创建新节点
        • createDocumentFragment() -创建文档碎片节点
        • createElement(tagname) -创建标签名为tagname的元素
        • createTextNode(text) -创建包含文本text的文本节点

    相关文章

      网友评论

          本文标题:JavaScript 的那些坑

          本文链接:https://www.haomeiwen.com/subject/pttzlxtx.html