zoukankan      html  css  js  c++  java
  • 那些年我们一起踩过的坑(javascript常见的陷阱)

    1.object最后一个逗号
    定义object直接量或json,最后一个逗号多写了,在ie下会报错,高级浏览器则不会,给只使用chrome调试的同学敲个警钟。踩了无数次这个坑了。
     
    2.自动加分号
     
    自动加分号的机制把很多人惯坏了,就常常不写分号,但是自动加分号的机制并不是无条件的,如果语句以括号开始,就不会自动加分号,这个打包的时候经常遇到,两个js都没问题,但是合并成一个就有问题,原因是前一个js文件结尾没写分号,下一个文件的开始字符是一个大闭包,编译器会认为文件1的最后一行和文件2的第一行是同一个语句没结束,就会产生语法错误。为了独善其身,各扫门前雪,很多同学都习惯在自己的闭包之前加分号,所以看到这个不要很奇怪,只是在做防御性编程。
    ;(function (){
     
    })()
    3.this的引用不确定
    call和apply可以绑定this,另外在对象方法中再定义闭包函数,闭包函数直接调用时this是指向window的,所以一般的方法是定义一个self或that变量把this存起来,利用闭包作用域访问暂存的变量。
    var MyObject={
    Name:"hello",
    test:function test(){
      var self=this;
       (function (){
         console.log(this.Name); //undeinfed
        console.log(self.Name);//hello
       })()
    }
    }
    MyObject.test()
     
    另外注意一点,我这里Name大写了,如果小写的name,第一个console.log输出一个空字符串,原因是引用到window.name了,window.name是一个神奇的存在,它的值可以存储在浏览器进程级别,刷新浏览器也不会消失。
     
    4.replace默认只替换一次
    用正则,不解释
     
    5.parseInt的进制
    如果值是0开始的,默认会按8进制解析,这个问题IE8以上已经修正,所以要用低版本IE才能测出这个问题,当初做日期控件时候踩到过这个坑,当时还是IE6的时代啊。
     
    6.for..in会遍历原型
    这也是为啥绝对禁止改写Object.prototype,如果哪位同学不小心手贱改了Object.protype就会殃及池鱼了,不是每个人在写for..in时都有习惯去用hasOwnProperty检则是否原型属性的。
     
     
    7.attachEvent的this绑定到window
    IE绑定事件的时候没把this指向到当前的dom元素,如果自己封装事件绑定函数可以用apply传进去,当然最好还是用jquery。
     
     
    8.在循环体中定义闭包的作用域问题
     
    var links=document.links;
     for(var i=0;i<links.length;i++){ 
       links[i].onclick=function(){ 
         alert(i); 
       } 
    }
     
    在onclick的事件中,alert(i);运行的时候查找当前作用域没有i,去上一级的变量对象中查找i,因为当按钮点击时,循环早已执行完,所以上一层的变量对象中i的值是最后一次循环的值。
     
    解决方法是多定义一层闭包并立即执行,在每一次循环都生成一个独立的闭包作用域把i值初始化进去。
     
    var links=document.links;
     for(var i=0;i<links.length;i++){ 
       (function (i){
       links[i].onclick=function(){ 
         alert(i); 
       } 
       })(i)
    }

     
    9.不加var变量会声明到全局window
    漏写了var 就会定义到window,由于编译器会自动查找作用域链,对程序的功能无影响,所以很难发现这个问题,会污染全局全量,可能就要jslint之类的review工具来检查了。
     
    10.函数的提前声明与var的提前声明
     
    函数不管在哪里声明,都会提前到当前作用域的最前面,而且是已经赋过值的(函数表达式则不是),var 声明的变量会提前到最前面,但是初始值是undefined,赋值语句要等执行到那一行才会赋值。
     
    来看这个例子

    function fn(a) {
    console.log("a第一次值:",a); //输出值是function a,因为函数提前定义了
    var a = 2;
      function a() { //定义一个空函数a

       }
    console.log("a第一次值:",a);  //输出值为2,第二行代码重新给a赋值了
    }
    fn("hello");

     
    11.arguments不是数组
    arguments虽然看起来像数组,但是千万不要当数据来push,pop啊,你不知道arguments还有callee,caller属性吗,它不是数组,也没有从Array.prototype继承,
     
    function test(){
    console.log(arguments instanceof Array);//false
    }
    test()
     
    如果要当数组使用就先转换成数组再用吧。
     
    12 操作符的隐式转换
     
    双等号,+号都会隐式转换,具体的转换规则很算杂,有一个类似乘法口决表的表格。
     
    13 日期对象的month从0开始
     
    月份又不是数组,不知为啥从0开始,year和date又是从1开始的,同时日期的年月日,感觉不是一个妈生的,实现不一致啊,不符合正常人的思维,每次使用时都要+1
     
    new Date().getMonth()+1
     
    14 getYear与getFullYear
    getYear得到的是从1970年开始的日期差值,但是在IE9以下getYear得到的却是完整年份,如果你只在IE9下写程序测试,到chrome下运行结果完全不对了,反之也是一样,今年2016年得到的getYear()是116,但是ie9以下却能得到2016。任何情况下都不要用getFullYear吧,getYear就是个多余的错误设计。
     
  • 相关阅读:
    博客迁移.
    win10不能睡眠问题
    我多希望没有遇见你
    打印队列 UVA12100
    理科工具——数值分析计算相关软件及下载地址
    用原生js完成鼠标点击显示滑入滑出效果
    javascript:用原生js模拟贪吃蛇游戏练习
    阅读css官方参考手册的关键点
    翻滚吧骰子!——flex布局加css3动画综合练习
    flexible box布局微博客户端发现页面练习
  • 原文地址:https://www.cnblogs.com/windyfancy/p/5169187.html
Copyright © 2011-2022 走看看