類型轉(zhuǎn)換與錯誤處理

錯誤處理機制

1、Error 實例對象

js所有拋出的錯誤都是Error構(gòu)造函數(shù)的實例,參數(shù)表示錯誤提示,可以從實例的message屬性讀到

var err = new Error('出錯了');
err.message // "出錯了"
  • 拋出Error實例,執(zhí)行中斷

整個程序就中斷在發(fā)生錯誤的地方,不再執(zhí)行后面代碼

  • 屬性
    • message:錯誤提示信息
    • name:錯誤名稱(非標準屬性)
    • stack:查看錯誤發(fā)生時的堆棧(非標準屬性)
function throwit() {
  throw new Error('');//拋出
}

function catchit() {
  try {
    throwit();
  } catch(e) {
    console.log(e.stack); // print stack trace
  }
}

catchit()
// Error
//    at throwit (~/examples/throwcatch.js:9:11)
//    at catchit (~/examples/throwcatch.js:3:9)
//    at repl:1:5

錯誤堆棧的最內(nèi)層是throwit函數(shù),然后是catchit函數(shù),最后是函數(shù)的運行環(huán)境

2、自定義錯誤

function UserError(message) {
  this.message = message || '默認信息';
  this.name = 'UserError';
}
//自定義錯誤對象
throw new UserError('出錯了!');

3、throw語句

用來手動中斷程序執(zhí)行,拋出一個錯誤

實際上,throw可以拋出任何類型的值

  • 錯誤對象

    function UserError(message) {
      this.message = message || '默認信息';
      this.name = 'UserError';
    }
    //自定義錯誤對象
    throw new UserError('出錯了!');
    
  • 其他類型

    // 拋出一個字符串
    throw 'Error!';
    // Uncaught Error!
    
    // 拋出一個數(shù)值
    throw 42;
    // Uncaught 42
    
    // 拋出一個布爾值
    throw true;
    // Uncaught true
    
    // 拋出一個對象
    throw {
      toString: function () {
        return 'Error!';
      }
    };
    // Uncaught {toString: ?}
    

4、try...catch語句

允許對錯誤進行處理,選擇是否往下執(zhí)行

try {
  throw "出錯了";
} catch (e) {
  console.log(111);
}
console.log(222);
// 111
// 222
  • 不中斷

catch代碼塊捕獲try中拋出的錯誤之后,程序不會中斷(除非return),會繼續(xù)執(zhí)行下去

  • 可嵌套

可以嵌套使用try...catch結(jié)構(gòu)

5、finally代碼塊

try...catch最后添加finally,不管是否出現(xiàn)錯誤,最后必需運行的語句

  • 錯誤沒有捕獲,中斷

    沒有catch捕獲錯誤,執(zhí)行finally后,程序就中斷在錯誤拋出的地方

try {
    throw new Error('出錯了……');
    console.log('此行不會執(zhí)行');
  } finally {
    console.log('完成清理工作');
  }
// 完成清理工作
// Error: 出錯了……
  • try / catch 有return

    try中return,延遲到finally執(zhí)行完再返回

    var count = 0;
    function countUp() {
      try {
        return count;
      } finally {
        count++;
      }
    }
    
    countUp()
    // 0
    count
    // 1
    

    try中throw,catch也有return,在catch中return時,跳到finally執(zhí)行(如果finally沒return,會等finally執(zhí)行完,再執(zhí)行catch中return;如果return,則不會執(zhí)行catch中的return語句

    try{}catch{}finally{}中存在return,則該結(jié)構(gòu)后面的語句不執(zhí)行

    function f() {
      try {
        console.log(0);
        throw 'bug';
      } catch(e) {
        console.log(1);
        return true; // 這句原本會延遲到 finally 代碼塊結(jié)束再執(zhí)行
        console.log(2); // 不會運行
      } finally {
        console.log(3);
        return false; // 這句會覆蓋掉前面那句 return
        console.log(4); // 不會運行
      }
    
      console.log(5); // 不會運行
    }
    
    var result = f();
    // 0
    // 1
    // 3
    
    result
    // false
    
  • try / catch 有throw

    try中throw,之后語句不執(zhí)行,跳到catch執(zhí)行

    try中throw,catch也有throw,在catch中throw時,跳到finally執(zhí)行(如果finally沒return,會等finally執(zhí)行完,再執(zhí)行catch中throw;如果return,則不會執(zhí)行catch中的throw語句

    function f() {
      try {
        throw '出錯了!';
      } catch(e) {
        console.log('捕捉到內(nèi)部錯誤');
        throw e; // 這句原本會等到finally結(jié)束再執(zhí)行
      } finally {
        return false; // 直接返回
      }
    }
    
    try {
      f();
    } catch(e) {
      // 此處不會執(zhí)行
      console.log('caught outer "bogus"');
    }
    
    //  捕捉到內(nèi)部錯誤
    

類型轉(zhuǎn)換

強制轉(zhuǎn)換

1、Number()

  • 簡單數(shù)據(jù)類型

    // 數(shù)字 -> 數(shù)字
    Number(324) // 324
    
    /* 字符串  -> 1.全是數(shù)字:對應(yīng)數(shù)字   2.空串:0    3.含字母其他:NaN
    -----> Number將字符串轉(zhuǎn)為數(shù)值,比parseInt函數(shù)嚴格,只要有一個字符無法轉(zhuǎn)成數(shù)值,整個字符串就會被轉(zhuǎn)為NaN */
    parseInt('42 cats') // 42
    Number('42 cats') // NaN
    
    //布爾 -> true為1,false為0
    
    //null -> 0
    
    //undefined -> NaN
    
  • 對象類型

    除了包含單個數(shù)值的數(shù)組,其他都是NaN

    Number({a: 1}) // NaN
    Number([1, 2, 3]) // NaN
    Number([5]) // 5
    

    Number背后的轉(zhuǎn)換規(guī)則比較復(fù)雜:

    1、調(diào)用對象的valueOf方法

    返回的簡單數(shù)據(jù)類型,直接對返回結(jié)果使用Number(),結(jié)束

    2、調(diào)用對象的toString方法

    1中返回的是對象時,調(diào)用toString

    返回的簡單數(shù)據(jù)類型,直接對返回結(jié)果使用Number(),結(jié)束

    3、報錯

    2中toString方法返回的是對象,就報錯

2、String()

  • 簡單數(shù)據(jù)類型

    • 數(shù)值:轉(zhuǎn)為相應(yīng)的字符串
    • 字符串:原來的值
    • 布爾值"true","false"
    • undefined"undefined"
    • null"null"
  • 對象類型

    • 對象,返回一個類型字符串
    • 數(shù)組,返回該數(shù)組的字符串形式
    String({a: 1}) // "[object Object]"
    String([1, 2, 3]) // "1,2,3"
    

    String()轉(zhuǎn)換規(guī)則

    Number方法基本相同,只是互換了valueOf方法和toString方法的執(zhí)行順序

    String({a: 1})
    // "[object Object]"
    
    // 等同于
    String({a: 1}.toString())
    // "[object Object]"
    

3、Boolean()

  • false五種情況

    除了以下五個轉(zhuǎn)換為false,其余為true

    • undefined

    • null

    • -0 或 +0

      Boolean(0) // false
      
    • NaN

    • ' '(空字符串)

  • 對象都是true,false對應(yīng)的布爾對象也是

    Boolean({}) // true
    Boolean([]) // true
    Boolean(new Boolean(false)) // true
    

自動轉(zhuǎn)換

1、布爾值

預(yù)期為布爾值的地方(比如if語句的條件部分),會自動轉(zhuǎn)換為布爾值

將一個表達式轉(zhuǎn)為布爾值

// 寫法一
expression ? true : false

// 寫法二
!! expression

2、字符串

字符串的加法運算,一個值為字符串,一個非字符串

具體規(guī)則是,先將復(fù)合類型的值轉(zhuǎn)為原始類型的值,再將原始類型的值轉(zhuǎn)為字符串

'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"

3、數(shù)值

  • 其他運算符(除了+)
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN
  • 一元運算符

    一元運算符也會把運算子轉(zhuǎn)成數(shù)值

+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0

set數(shù)據(jù)結(jié)構(gòu)

// 
// 1.接收一個數(shù)組參數(shù), 將數(shù)組去重再保存
// 2.set.clear()清空set 無返回值 返回undefined
// 3.set.add(val)添加某個值,返回set對象本身{1,2,3,4,5}
// 4.set.delete(val)刪除某個值,返回是否刪除成功
// 5.set.has(val)查找某個值,返回是否包含
// 6.set.size屬性 值的個數(shù)
// 數(shù)組的去重
let arr = [1,2,3,4,5,1,2];
let set = new Set(arr);
arr = [...set];

map數(shù)據(jù)結(jié)構(gòu)

// map數(shù)據(jù)結(jié)構(gòu) :類似于對象
// 1.接收一個二維數(shù)組,將數(shù)組轉(zhuǎn)化成key-value的形式
// 2.map.clear()清空 map變?yōu)閧}
// 3.map.get(key)獲取key對應(yīng)的value值
// 4.map.has(key) 返回是否包含
// 5.map.set(key,val)修改或增加key
// 6.map.delete(key) 返回是否刪除成功
// 7.map.size屬性 值的個數(shù)
let arr=[
    ['a',1],
    ['a2',2],
    ['a3',3]
]
let map = new Map(arr);
console.log(map);
// {'a'=>1,'a'=>2,'a'=>3} 

數(shù)組鍵名

1、數(shù)組的鍵名可以是整數(shù)或字符串?

arr = [1,2,3];
arr[0] //1
arr['0']  //1
arr.0//報錯

之所以可以用數(shù)值讀取,是因為非字符串的鍵名會被轉(zhuǎn)為字符串

(方括號是運算符,可以接受數(shù)值,點結(jié)構(gòu)不能)

2、數(shù)組的本質(zhì)

是個對象

arr = [];
typeof arr;//object

3、length屬性是可寫的

可用來清空數(shù)組,將length屬性設(shè)為0

var arr = [ 'a', 'b', 'c' ];
arr.length = 0;
arr // []

人為設(shè)置length大于當前元素個數(shù),會自動新增,新增位置為空

var a = ['a'];
a.length = 3;
a[1] // undefined

小于,則會自動刪除多余元素

注意:使用delete命令刪除數(shù)組元素,會形成空位,length不變

類似數(shù)組的對象

一個對象的所有鍵名都是正整數(shù)或零,并有length屬性,這個對象就很像數(shù)組,但不是數(shù)組。

1、和數(shù)組的區(qū)別

  • 他沒有數(shù)組特有的方法,且length為靜態(tài),不隨元素變化而變化
var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

obj[0] // 'a'
obj[1] // 'b'
obj.length // 3
obj.push('d') // TypeError: obj.push is not a function

2、有哪些例子

以下例子可以:使用[ ]獲取元素,用length獲取長度,但instanceof Array為false

  • 函數(shù)的不定參數(shù)arguments
  • DOM元素集
  • 字符串

3、轉(zhuǎn)換為真正數(shù)組

有以下幾種方法:

  • 使用數(shù)組方法slice,轉(zhuǎn)換為真正數(shù)組

    var arr = Array.prototype.slice.call(arguments);
    arr.forEach((element, index) => {
    
    })
    
  • 使用call調(diào)用數(shù)組方法

    Array.prototype.forEach.call(arguments, (element, index) => {
        //等同于調(diào)用for循環(huán)
    })
    

    但是,真正轉(zhuǎn)為數(shù)組,再使用數(shù)組方法要比后面的方法快

對象

obj = {
    age: 18,
    name: "ccc"
}
var a = "sex";
obj[a] = "female";//name: "female"
obj.a = "female";//a: "female"

(方括號是運算符,可以接受變量,點結(jié)構(gòu)不能)

函數(shù)新增方法

// 函數(shù)新增方法
// 箭頭函數(shù)
// 1.箭頭函數(shù)使用()=>返回值,可以直接接收返回值,不用return
// 2.箭頭函數(shù)沒有不定參數(shù)arguments,可以使用(...arg)剩余參數(shù)接收多個參數(shù),組成一個數(shù)組來獲取參數(shù)
// 3.箭頭函數(shù)沒有this 調(diào)用箭頭函數(shù)的this,指向聲明時的作用域的this

數(shù)組新增方法

// 數(shù)組新增方法
// 1.flat(depth) 參數(shù)為遞歸層數(shù),不改變原數(shù)組
let arr = [1,[2,3,[4],5],6];
let arr2 = arr.flat(Infinity);
console.log(arr2);

// 2.flatMap(callback) 只能遞歸一層,返回新組成的數(shù)組
let arr = [['a1',['11','11']],['a2','15']];
let arr2 = arr.flatMap((item, index) => {
    console.log(item,index);
    // 這里return item相當于flat遞歸一層,將第一層元素為數(shù)組的轉(zhuǎn)為元素
    item = item.filter((item,index) => {
        return index == 0;
    })
    return item;
})
console.log(arr2);

// 3.find(callback)返回第一個滿足要求的值 都沒有就是undefined
let arr = [1,2,3,4,5,1,2];
let val = arr.find((item,index)=>{
    if(item>3){
        return true;
    }
});
// 或者
val = arr.find(item => item > 2);
console.log(val);

// 4.findIndex(callback)
let i = arr.findIndex(item => item > 2);

對象新增的方法

// 對象新增的方法
// 1.簡潔表示法
// 1.1屬性簡潔表示
// 1.2方法簡潔表示
// 2.屬性名表達式[]
let age = 10;
let name = 'ccc';
let a = 'sex';
let person = {
    name,
    age,
    [a]: 'man',
    say(){
        console('say:function() => say(){}');
    }
}
console.log(person);

// 對象合并
let obj = {a:1,b:2};
let obj2 = {c:3,d:4};
obj2 = Object.assign(obj2, obj);
console.log(obj2);
let obj2 = {
    ...obj,
    c: 3,
    d: 4
};
console.log(obj3);


//is()對象比較
// 1.和===大部分相同,例如以下都是true
// 兩個值都是undefined
// 兩個值都是null
// 兩個值都是true或者false
// 兩個值都是相同字符串
// 兩個值都是同一個對象(地址相同)
// 兩個值都是數(shù)字
// 2.區(qū)別:
// +0 -0
// NaN NaN
console.log(Object.is(+0,-0))//false
console.log(+0 === -0)//true
console.log(NaN === NaN)//false
console.log(Object.is(NaN,NaN))//true

var與let

區(qū)別:塊級作用域

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
  • var命令聲明的,在全局范圍內(nèi)都有效,因此全局只有一個i,所有數(shù)組成員的函數(shù)內(nèi)部的i,指向的都是同一個i,每一次循環(huán),i值改變,最后為10
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6
  • let聲明的,只在本輪循環(huán)有效,每一次循環(huán)i是一個新的變量,JavaScript 引擎內(nèi)部會記住上一輪循環(huán)的值,在此基礎(chǔ)上進行計算新的i

for循環(huán)作用域

循環(huán)變量的那部分是一個父作用域,而循環(huán)體內(nèi)部是一個單獨的子作用域

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc
//說明各自單獨的作用域

Babel的使用

<!-- babel -->
<!-- 一個js的編譯器,可以把es6里面的語法糖轉(zhuǎn)換為瀏覽器可以識別的js語法 -->
<!-- 具體的使用 -->
<!-- 1.引入babel文件 -->

<script src = "js/babel.min.js"> </script>
<script type = "text/babel">
    let obj = {a:1};
    let obj2 = {
        c:3,
        ...obj,
        c(){
            console.log("babel編譯器 看瀏覽器代碼是否變了");
        }
    }
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容