04-常见错误,异常处理以及this总结

本文详细介绍了JavaScript中的常见错误类型,包括语法错误、引用错误、类型错误、范围错误和逻辑错误,以及如何通过异常处理来捕获和处理这些错误。此外,文章深入探讨了逻辑与和逻辑或的用法。重点讲解了同步和异步代码中的闭包应用,并列举多个实例解释了this关键字在不同场景下的指向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常见错误

一、js中的错误分类

错误分类通常分为:语法错误 、引用错误、类型错误、范围错误和逻辑错误

1.语法错误

JS代码在预编译时 就发现了错误
特点:代码没有机会执行,错误最好找

<script>
    function ()  //语法错误(没有写函数名)
    {

    }    
</script>
Uncaught SyntaxError: Function statements require a function name
2.引用错误

通常访问一个没有定义的变量就会发生引用错误
解决办法:先定义好这个变量,再使用之
特点:JS代码在执行时的时候,才会发现引用错误,错误之后的代码就不执行

<script>
    console.log("start")
    // index.html:38 Uncaught ReferenceError: a is not defined
    console.log(a);     // 引用错误
    console.log("end")
</script>
Uncaught ReferenceError: a is not defined
3.类型错误

使用类型不当,你提供的数据,不符合js的数据类型规范
特点:在JS代码在执行时才会发现,类型错误之前的代码也会执行,之后的代码不会执行。
解决办法:一般是你数据类型使用不当,修改之就OK了

<script>

    console.log("start")
    var f = 110;
    f();    // 类型错误
    console.log("end")
</script>
TypeError: f is not a function
4.范围错误

使用容器,范围指定不当

var arr = new Array(-5);
Uncaught RangeError: Invalid array length  
5.逻辑错误

上面的4类错误,在控制台都会报错,修改就OK了。还有一类错误,控制台不会报错,叫逻辑错误。
逻辑错误解决办法:通过debugger调试错误。

二、异常处理

异常不是错误,异常是指可能出错的代码。

语法:
try{
// 放可能出错的代码
}catch(e){
// 如果上面的代码错误了,就到这里进行错误的处理,其中e表示错误对象
// 它里面包含了错误信息。通过查看e,可以知道它到底出了什么错误
}finally{
// 无论对错,代码都会执行到此处,在JS中用的不多
}

<script>
   try{
       console.log(a); // 放可能出错的代码
   }catch (e) {
       console.log("有错误:",e);
   }finally {
       console.log("最终finally一定会执行");
   }
</script>

三、逻辑与 和 逻辑或

逻辑与 && :双元运算符,有两个操作数。只有两个操作数都为真,整体的结果才为真

true && true 真
true && false 假
false && true 假
false && false 假

逻辑或 || :双元运算符,有两个操作数。 只要有一个操作数为真,整体的结果就为真

true || true 真
true || false 真
false || true 真
false || false 假

逻辑非 ! :单目运算符,1个操作数

!true  假
!false  真

如果说第一个操作数能决定整体的值,JS会停止对第二个操作数的运算

<script>
    var a = 10;
    var b = 0;
	var c = b && a++;  // b的值是false 按理说是把false赋值给c  c的值是false  但是&&得到的值不是隐式类型转化后的值,是隐式类型转化之前的值
    var d = a++ && b;  // a++后  a的值是11  整体的值是10  10转成true   不能确定  看第2个操作数  b是0  0转成false  整体就是false  第1个操作数不能确定整体的值,那么整体的值就是第2个操作数的值
    console.log(a);  // 11
    console.log(b);  // 0
    console.log(c);  // 0
    console.log(d);  // 0
</script>

第1个操作数不能确定整体的值,那么整体的值就是第2个操作数的值

<script>
    var a = 0;
    var b = 2;
    var c = a || b++;
    console.log(a);  // 0
    console.log(b);  // 3
    console.log(c);  // 2

    var m = 1;
    var n = "";
    var q = m || n;
    console.log(m);   // 1
    console.log(n);  // ""
    console.log(q);  // 1
</script>

四、同步和异步代码(闭包的使用)

同步:代码的书写顺序和代码的执行顺序一样。
异步:代码的书写顺序和代码的执行顺序不一样。

一般同步代码执行之后,异步代码才进行执行

98%代码都是同步代码。
在JS中,异步代码仅仅是个别:
1)事件绑定
2)定时器
3)ajax

<ul>
 <li>click me</li>
 <li>click me</li>
 <li>click me</li>
 <li>click me</li>
</ul>


<script>
    var elements=document.getElementsByTagName('li');
    var length=elements.length;
    for(var i=0;i<length;i++){
        elements[i].onclick=function(){
        alert(i);
    }
 }
</script>

执行结果为: 5 5 5 5 5。同步代码与异步代码出现时,先执行同步代码,同步代码执行过之后,i的值为5,异步代码执行时,将i的最后数值输出5次,所以最后输出结果为5 5 5 5 5。

显示异步代码与同步代码一同执行

实现效果:依次点击按钮1,2,3时,控制台分别输出0,1,2数值

1)使用函数闭包,返回信息
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>

<script>
    var btns = document.getElementsByTagName("button"); // 数组容器
    // bnts.length; 说明数组也是对象  arr[0]  obj.name  矩形和正方形
    // 同步代码
    for (var i=0; i<btns.length; i++){
        // 事件绑定  异步代码  浏览器在执行时直接忽略掉
        btns[i].onclick = (function (i) {
            return function g() {
                console.log(i)
            }
        })(i);
    }
</script>


2)利用数组绑定事件源
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>

<script>
    var btns = document.getElementsByTagName("button");
    for (var i=0; i<btns.length; i++){
        // console.log(btns[i].abc)// 访问一个对象上不存在的属性  得到的是und
        btns[i].index = i; // 把i值赋值给对象上的index属性
        btns[i].onclick = function () {

            console.log(this.index);   //绑定事件源
        }
    }
</script>


浏览器会帮我们自动调用函数,
3)let形成块级作用域
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>

<script>
    var btns = document.getElementsByTagName("button");
    for (let i=0; i<btns.length; i++){
        btns[i].onclick = function () {
            console.log(i)
        }
    }
</script>


五、this大总结

结论:
   1)如果this出现在普通的函数中,this表示window,如果你通过window打点调用一个函数,这个函数中的this也是window。
   2)事件绑定,事件处理程序,事件发生时,浏览器帮我们调用这个函数,此函数中的this表示事件源
   3)在一个对象中,如果有方法(函数),如果通过这个对象调用方法,方法中的this表示这个对象
   4)在IIFE中,this表示window
   5)前四点都是在非严格模式下,在严格模式下,调用一个普通函数,this表示undefined。IIFE中的this也表示undefined

案例01
1.代码
<button id="box">box</button>
<script>
    let box = document.getElementById("box");
    box.onclick = function () {
        console.log(this); // this表示事件源
    }
</script>

2.解析

解析:onclick是事件调用时间,代表鼠标点击之后,事件发生相应的活动。并且,浏览器帮我们调用这个函数,此时的this满足条件2),即this表示事件源。

案例02
1.代码
<button id="box">box</button>

<script>
    let box = document.getElementById("box");
    function f() {
        console.log(this); // window
    }
    f();  程序员自己调用一个函数  一个普通函数  函数中的this表示window
    box.onclick = f();
</script>
2.解析

解析:其中f();代表普通函数调用,符合条件1),所以函数里面的this表示的是window。执行box.onclick = f();这一行, 主要看 = 后面f(); 表示函数普通调用,符合条件1)所以这里的this也代表window。

案例03
1.代码
<button id="box">box</button>

 <script>
    let box = document.getElementById("box");
    function f(){
        console.log(this);  // window
        return function g(){
            console.log(this); // 事件源
        }
    }
    box.onclick = f();
</script>

2.解析

解析:box.onclick表示响应事件,调用函数f();符合条件1),所以第一个this表示window。因为函数返回的是一个堆地址,这个堆地址浏览器自动调用,并且进行了事件绑定,所以符合条件2),因此第二个this表示事件源。

案例03
1.代码
<script>
    function k() {
        console.log(this); // window
    }
    window.k();  // window打点调用
    k(); // 程序员自己调用
</script>
2.解析

解析:因为由window加点进行调用,符合条件1),所以这个this也表示window。函数k由自己调用k();符合条件1),所以第一个this表示window。

案例04
1.代码
<script>
    // JS中的对象是属性的无序集合
    // 属性:变量/方法
    // 无序:容器中的属性没有顺序
    // 集合:存放了N个数据
    var wc = {
        name:"wangcai",  // 属性  var name = "wangcai"
        age:100,   // 属性
        eat:function () {    // 叫方法(属性)
            console.log("eat...")
            console.log(this);
        }
    }
    // 一个方法中的this是谁,就看点前面是谁。
    wc.eat(); // 调用一个对象上的方法
</script>

2.解析

解析:this是通过wc对象调用的,这里的this指的是对象wc。

案例05
1.代码
<script>
    var name = "window";
    var Wangcai = {
        name:"Wangcai",
        show:function () {
            console.log(this.name)
        },
        f:function () {
            var fun = this.show;
            fun(); // 普通函数调用
        }
    }
    Wangcai.f();
</script>

2.解析

解析:执行Wangcai.f();语句,函数f是通过Wangcai这个对象调用的,所以this.show中的this指的是对象Wangcai。调用函数fun是函数的普通调用,所以this.name中的this指的是window。

案例06
1.代码
<script>
    var fullname = "language";
    var obj = {
        fullname:"javascript",
        prop:{
            getFullName:function () {
                return  this.fullname;
            }
        }
    }
    // 谁用了getFullName  看.前面是谁
    // .前面是obj.prop  说明getFullName中的this是obj.prop
    // 问:obj.prop中有没有fullname;
    // 答:访问一个对象上不存在的属性  得到und
    console.log(obj.prop.getFullName()); // undefined
</script>
2.解析

解析:函数getFullName()点的前面是obj.prop,其中对象obj中的prop属性中没有fullname属性,所以此时的this属性指的是undefined。

案例07
1.代码
<script>
    var fullname = "language";
    var obj = {
        fullname:"javascript",
        prop:{
            fullname:"vue",
            getFullName:function () {
                return  this.fullname;
            }
        }
    }
    var t = obj.prop.getFullName;
    console.log(t());
</script>

2.解析

解析:其中obj.prop.getFullName表示的是function () { return this.fullname;}返回的堆地址,调用t使用的是t(),即普通函数调用,符合条件1),所以此时的this表示的是window,最后输出结果为全局变量中的fullname:language。

案例08
1.代码
<script>
    let obj = {
        fn:(function () {
            return function () {
                console.log(this)
            }
        })()
    }
    obj.fn();
</script>
2.解析

解析:函数fn是立即调用函数(IIFE),此时内部使用对象obj调用,符合条件3),此时的this指的是obj这个对象。

案例09
1.代码

<script>
    let obj = {
        fn:(function () {
            return function () {
                console.log(this)
            }
        })()
    }
    var t = obj.fn;
    t();
</script>
2.解析

解析:对象obj中的fn函数将内部返回地址赋值给t,调用普通函数t(); ,符合条件1)此时的this表示的是window。

案例10
1.代码
<script>
    (function fn() { 
         console.log(this)
    })();
</script>
2.解析

解析:函数属于立即调用函数(IIFE),符合条件4),此时的this表示window。

案例11
1.代码
<script>
    "use strict"; // 启用JS的严格模式
    function f() {
        console.log(this); // und
    }
    f();

    (function () {
        console.log(this); // und
    })();
</script>
2.解析

解析:严格模式下,this的值指的是undefined。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值