资讯专栏INFORMATION COLUMN

JavaScripr中常遇到的错误和this关键字

klinson / 1181人阅读

摘要:通过使用提供的异常处理语句,可以用结构化的方式来捕捉发生的错误,让异常处理带啊与核心业务代码实现分离。错误与异常处理在应用中的重要性是毋庸置疑的。包括内置对象函数在内的所有函数都可以用来调用,这种函数调用被称为构造函数调用。

错误与异常 概念

错误与异常是什么
错误,指程序中的费正常运行状态,在其他编程语言中称为‘异常’或‘错误’。解释器会为每一个错误创建并抛出一个Error对象,其中包含错误额描述信息。
通过使用JavaScript提供的异常处理语句,可以用结构化的方式来捕捉发生的错误,让异常处理带啊与核心业务代码实现分离。
错误与异常处理在应用中的重要性是毋庸置疑的。任何有影响力的Web应用都需要一套完善的错误处理机制。

try...catch语句

try...catch语句作为JavaScript中处理异常的一种标准方式。try语句标记一块待尝试的语句,如果该语句出现错误,则通过catch语句进行捕获。

try {
    console.log(v);//调用变量,但没有定义--报错!
} catch(e){
        console.log(e);//表示try语句中出现错误的信息
       // e--全拼error表示语句中出现错误的信息
}
捕捉块

可以使用捕捉块来处理所有可能正在try代码块中产生的异常。

catch(catchID) {
    console.log();
}

捕捉块指定了一个标识符(上述语句中的catchID)来存放抛出语句指定的值。
可以用这个标识符来获取抛出的异常信息。

终结快

终结快包含了哎try和catch快完成后、下面的语句会接着执行之前的语句。终结快无论是否抛出异常都会执行。如果抛出了一个异常,就算没有异常处理,终结快的语句也会执行。

try {
    console.log(v);
} catch(error){
    console.log(error)
}
finally{
    接着执行的语句
}
嵌套try...catch语句

可以嵌套一个或多个try...catch语句。如果一个内部的try...catch语句没有捕捉块,将会启动匹配外部的try...catch语句的捕捉快。

try {
    console.log(v);
} catch(error){
    try {
        console.log(a);
    } catch(error){
        console.log(error);
    }
}
finally{
    
}
错误类型

基本错误类型
执行低吗期间可能会发生的错误有多中类型,每种错误都有对应的出错误类型。当错误发生时,就会抛出对应类型的错误对象。
Error是基本错误类型,其他错误类型都继承自该类型。Error类型打的错误很少见,如果有也是浏览器抛出的。这个基本错误类型的主要目的是提供给开发人员抛出自定义错误的。

this关键字 概念 this是什么

this关键字是JavaScript中最复杂的机制之一。他是一个很特别的关键字,被自动定义在所有函数的作用域中,但是即使是非常有经验JavaScript开发者也很难说清它到底指向什么。
实际上,JavaScript中this的机制并没有那么先进,但是开发者往往会把理解过程复杂化。毫不夸张的说,不理解他的含义,大部分开发都无法完成。
this都有一个共同点,它总是返回一个对象。简单来说,this就是属性或方法‘当前’所在的对象。

//定义一个全局变量
var v = 100;
function fn(){
//this经常被定义在函数的作用域中
//this总是要返回一个对象
    console.log(this.v);//this指向哪个对象,不取决于函数定义的位置,而是取决于调用的位置
}
fn();//函数调用
为什么使用this

this提供了一种更优雅的方式隐式‘传递’一个对象引用,因此可以将API设计的更加简洁并且易于复用。
随着使用模式越来越复杂,显示传递上下文对象会让代码变得越来越混乱,使用this则不会这样。

调用位置

想要了解this的绑定过程,首先要理解调用位置,调用位置就是函数在代码中被调用的位置(而不是声明的位置)。
通常来说,寻找调用位置就是寻找‘函数被调用的位置’。最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数)。

绑定规则 默认绑定

在一个函数中使用this,当该函数被独立调用。可以把这条规则看做无法应用其他规则时的默认规则。

var a = 100;//定义一个全局变量
function foo(){
    console.log(this.a);
    }
foo();//调用
隐式绑定

隐式绑定的规则需要考虑的是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含。当然,这种说法并不正确。
调用位置会使用obj上下文来引用函数,因此可以说函数被调用是obj对象‘拥有’或‘包含’它。

//定义一个对象
var obj = {
    v :200,
    f:fn  //对象的f()方法指向fn()函数
}
//定义一个全局变量,并且赋值为对象obj的f()方法
var fun = obj.f;
fun();

隐式绑定是最常见的this绑定问题,指的就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把this绑定到全局对象。
fun是obj.f的一个引用,但是实际上,他引用的是f函数本身,因此此时的fun()其实是一个不带任何修饰的函数调用,因此应用了默认绑定。

显示绑定

显示绑定就是明确在调用时,this所绑定的对象。JavaScript中提供了apply()方法和call()方法实现。这两个方法打的第一个参数接收的是一个对象,会吧这个对象绑定到this,接着在调用函数时指定这个this。

//定义一个全局变量
var a = 100;
//定义一个函数
function fn(){
    console.log(this.a);
}
//定义一个对象
var obj = {
    v:200,
    f:fn   //对象的f()方法指向fn()函数
}
//定义一个全局对象
var fun = obj.f;
//将fun作为函数进行调用
fun.apply(obj);
new绑定

在JavaScript中,构造函数只是一些使用new操作符是被调用的函数。包括内置对象函数在内的所有函数都可以用new来调用,这种函数调用被称为构造函数调用。
使用new来调用函数胡,会自动执行下面的操作:
1.创建(或者说构造)一个全新的对象。
2.这个新对象会绑定到函数调用的this.
3.如果函数没有返回其他对象,那么new表达式中的函数调用会自动回这个对象。

function Hero(name){
    this.name = name;
}
//this取决于函数调用的位置
var hero1 = new Hero("张三");
var hero2 = new Hero("李四");
绑定例外 被忽略的this

如果把null或者undefined作为this的绑定对象传入call、apply或者bingd,这些值在调用时会被忽略,实际应用的是默认绑定规则。

function fn(){
    console.log(this.v);
}
var v = 200;
fn.call(null);

var result = Math.max.apply(null,[1,2,3,4,5,2,3,]);
console.log(result);
间接引用

有可能(有意或者无意地)创建一个函数的“间接引用”,在这种情况下,调用这个函数会应用默认绑定规则。

function foo(){
    console.log(this.a);
}
var a = 2;
var o = {
    a:3,
    foo:foo
};
var p = {
    a:4
};
o.foo()//3
(p.foo = o.foo);//2
注意事项 避免多层this

多层函数或方法嵌套可能导致不同层次this绑定的对象不同。

var o = {
    f1:function() {
        console.log(this);
        var f2 = function(){
            console.log(this);
        }();
    }
}
o.f1();

上述代码包含两层this,结果运行后,第一层指向对象o,第二层指向全局对象。

避免数组方法中this

数组的map和foreach方法,允许提供一个函数作为参数。这个函数内部不应该使用this。

var obj = {
    v:100
    arr:[1,2,3,4],
    f:function(){
        this.arr.forEach(function(value){
            console.log(this.v);
        })
    }
}
obj.f();
避免回调函数中的this

回调函数中的this经常会改变绑定的对象,最好的解决方案就是避免这样使用this。

var o = {
    name:"张三"
}
o.fn = function(){
    console.log(this.name);
}
var name = "李四";
function f(v){
    v();
}
f(o.fn);

上述代码中,f()方法的回调函数中this,其实就是指全局对象。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108490.html

相关文章

  • 在工作中常用到SQL

    摘要:前言只有光头才能变强。文本已收录至我的仓库,欢迎最近在公司做了几张报表,还记得刚开始要做报表的时候都快把给忘光了当时在广州休假了个月多,在实习期间也没咋写过,回到公司的第一个需求就是做报表。 前言 只有光头才能变强。文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近在公司做了几张报表,还记得刚开始要做报表的时...

    acrazing 评论0 收藏0
  • 项目开发中常常会遇到详情返回列表,列表默认在点击详情高度问题,特此总结一下,希望可以帮到你们

    摘要:从第二页返回首页时为只处理设置了路由元信息的组件简单的分享给大家,希望可以帮到你们 刚刚解了一个详情返回列表时候,列表高度保持在点击进去的详情的问题,特此做个分享,希望大家碰到类似的问题可以直接一遍过,不用卡壳(因为这个在实际项目开发中经常会用到所以分享了出来) Vue api 是这样说的 api链接传送门 showImg(https://segmentfault.com/img/b...

    lentrue 评论0 收藏0
  • 项目开发中常常会遇到详情返回列表,列表默认在点击详情高度问题,特此总结一下,希望可以帮到你们

    摘要:从第二页返回首页时为只处理设置了路由元信息的组件简单的分享给大家,希望可以帮到你们 刚刚解了一个详情返回列表时候,列表高度保持在点击进去的详情的问题,特此做个分享,希望大家碰到类似的问题可以直接一遍过,不用卡壳(因为这个在实际项目开发中经常会用到所以分享了出来) Vue api 是这样说的 api链接传送门 showImg(https://segmentfault.com/img/b...

    crelaber 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<