欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript高階教程之“==”隱藏下的類型轉(zhuǎn)換

 更新時間:2019年04月11日 10:54:57   作者:wuming  
這篇文章主要給大家介紹了關(guān)于JavaScript高階教程之“==”隱藏下類型轉(zhuǎn)換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

拋磚引玉

按照正常的邏輯來說,我們判斷兩個值是否相等會遵循以下規(guī)則:


但是我看下面一組值:

[]==0 //true
[]==false //true
[]==!{} //true
[10]==10 //true
'0'==false //true
''==0 //true
undefined==null //true 
!null==true //true 

居然沒有按照我們的劇本走,那它比較規(guī)則又是什么?下面我就來分析一波。

“==”的比較規(guī)則

首先我們先去ECMAScript5.1中文版( http://lzw.me/pages/ecmascrip... )找一下“==”的比較規(guī)則,如下:

1.若Type(x)與Type(y)相同, 則
    a.若Type(x)為Undefined, 返回true。
    b.若Type(x)為Null, 返回true。
    c.若Type(x)為Number, 則
        i.若x為NaN, 返回false。
        ii.若y為NaN, 返回false。
        iii.若x與y為相等數(shù)值, 返回true。
        iv.若x 為 +0 且 y為−0, 返回true。
        v.若x 為 −0 且 y為+0, 返回true。
        vi返回false。
    d.若Type(x)為String, 則當(dāng)x和y為完全相同的字符序列(長度相等且相同字符在相同位置)時返回true。 否則, 返回false。
    e.若Type(x)為Boolean, 當(dāng)x和y為同為true或者同為false時返回true。 否則, 返回false。
    f.當(dāng)x和y為引用同一對象時返回true。否則,返回false。
2.若x為null且y為undefined, 返回true。
3.若x為undefined且y為null, 返回true。
4.若Type(x) 為 Number 且 Type(y)為String, 返回comparison x == ToNumber(y)的結(jié)果。
5.若Type(x) 為 String 且 Type(y)為Number,返回比較ToNumber(x) == y的結(jié)果。
6.若Type(x)為Boolean, 返回比較ToNumber(x) == y的結(jié)果。
7.若Type(y)為Boolean, 返回比較x == ToNumber(y)的結(jié)果。
8.若Type(x)為String或Number,且Type(y)為Object,返回比較x == ToPrimitive(y)的結(jié)果。
9.若Type(x)為Object且Type(y)為String或Number, 返回比較ToPrimitive(x) == y的結(jié)果。
10.返回 false

看完ECMAScript5.1中文版的介紹之后,相信很多小伙伴的心情應(yīng)該是這樣的:


別看上面說的有點(diǎn)花里胡哨的,其實(shí)我們可以用很簡單的話來總結(jié)出來。由于本篇文章核心是“==”是如何進(jìn)行類型轉(zhuǎn)換,我就總結(jié)一下類型不同的情況下“==”是如何比較的。

  • 當(dāng)數(shù)據(jù)類型為Boolean類型或者String類型時,比較時需要轉(zhuǎn)換成Number類型。
  • 當(dāng)數(shù)據(jù)類型為引用類型時,需要轉(zhuǎn)換成原始數(shù)據(jù)類型。當(dāng)轉(zhuǎn)換后的原始數(shù)據(jù)類型為Boolean類型或者String類型,則繼續(xù)轉(zhuǎn)換成Number類型。
  • undefined和null跟任何值在“==”下都返回false,但二者在“==”下返回true。

具體流程圖如下:

備注:

Javascript的數(shù)據(jù)類型可以分為以下兩種:

  • 原始數(shù)據(jù)類型(null、undefined、Number、String、Boolean、Symbol(Es6才引入的))
  • 引用類型 (Object)

Boolean類型、String類型轉(zhuǎn)換成Number類型的規(guī)則(ToNumber)

Boolean類型

Boolean Number
true 1
false 0

 

String類型

標(biāo)準(zhǔn)的數(shù)字格式
如果是標(biāo)準(zhǔn)的數(shù)字格式,轉(zhuǎn)換成Number類型相比不用多說,比如下面這幾個栗子🌰:

"123" => 123
"12.34" => 12.34
"0.12" => 0.12
"-12.34" => -12.34

非標(biāo)準(zhǔn)的數(shù)字格式

但是如果是非標(biāo)準(zhǔn)的數(shù)據(jù)格式,要分兩種情況來考慮:

  • 第一種:只包含數(shù)字并且最多只有1個點(diǎn)。
  • 第二種:包含非數(shù)字以及含有多個1個點(diǎn)。

只包含數(shù)字并且最多只有1個點(diǎn)

這種情況下會首先進(jìn)行補(bǔ)0和去0的操作,下面看幾個栗子🌰:

"01234" => 1234
".1" => 0.1
"12." => 12
"1.000" => 1
"-02.30" => -2.3

包含非數(shù)字以及含有多個1個點(diǎn)

這種情況下統(tǒng)統(tǒng)返回NaN,意為“Not a Number”,這里我們要注意一下,NaN還是Number類型,下面看幾個栗子🌰:

"123aa4" => NaN
"哈嘍,DD" => NaN
typeof NaN => "numer"

引用類型轉(zhuǎn)換成原始數(shù)據(jù)類型的規(guī)則(ToPrimitive)

在介紹轉(zhuǎn)換規(guī)則之前,首先我們我們介紹一下引用類型都帶有的兩個方法:

  • Object.prototype.toString
  • Object.prototype.valueOf

這二者都可以將引用類型轉(zhuǎn)換成原始數(shù)據(jù)類型,接下來我們對二者做一個詳細(xì)的介紹:

Object.prototype.toString

MDN是這樣解釋的:

The toString() method returns a string representing the object.(toString()這個方法返回一個代表這個對象的字符串)

舉個栗子🌰:

const obj = {}
console.log(String(obj)) //"[object Object]"
obj.toString = function(){
 return 'Hello,Teacher Cang!'
}
console.log(String(obj)) //"Hello,Teacher Cang!"

Object.prototype.valueOf

MDN是這樣解釋的:

The valueOf() method returns the primitive value of the specified object.( valueOf()這個方法返回這個對象的原始數(shù)據(jù)值)

舉個栗子🌰:

const obj = {}
console.log(Number(obj)) //NaN
obj.valueOf = function(){
 return 12345;
}
console.log(Number(obj)) //12345

valueOf和toString的優(yōu)先級

關(guān)于這二者的優(yōu)先級,在不同的情況下有著不同的優(yōu)先級,下面我們根據(jù)不同情況介紹一下。

ToNumber

看個栗子🌰:

const obj = {
 toString(){
 console.log('調(diào)用了toString');
 return 'Hello,Teacher Cang!';
 },
 valueOf(){
 console.log('調(diào)用了valueOf');
 return 12345;
 }
}
console.log(Number(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了valueOf
12345

通過上面的代碼的運(yùn)行結(jié)果,我們得出這么一個結(jié)論:

在ToNumber情況下,valueOf的優(yōu)先級大于toString。

接下里我們看這么一種情況,如果valueOf返回的并不是原始數(shù)據(jù)類型會怎么樣。

const obj = {
 toString(){
 console.log('調(diào)用了toString');
 return 12345;
 },
 valueOf(){
 console.log('調(diào)用了valueOf');
 return {};
 }
}
console.log(Number(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了valueOf
調(diào)用了toString
12345

從上面的運(yùn)行結(jié)果中,我們可以得出這么一個結(jié)論:

在ToNumber情況下,如果valueOf返回的不是原始數(shù)據(jù)類型,則會自動調(diào)用toString。

打破砂鍋問到底,再來一個非常極端的情況,如果說valueOf和toString返回的都不是原始數(shù)據(jù)類型,這時又該怎么樣呢?同樣,我們繼續(xù)看一下運(yùn)行結(jié)果:

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return {};
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return {};
 }
}
console.log(Number(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了valueOf
調(diào)用了toString
Uncaught TypeError: Cannot convert object to primitive value

從上面的運(yùn)行結(jié)果中,我們再次可以得出這么一個結(jié)論:

在ToNumber情況下,如果valueOf和toString返回的都不是原始數(shù)據(jù)類型,那么js會拋出異常,提示無法將引用類型轉(zhuǎn)換原始數(shù)據(jù)類型。

根據(jù)三組代碼的運(yùn)行的結(jié)果,我們最后總結(jié)一下:

在ToNumber情況下,js會優(yōu)先調(diào)用valueOf,如果valueOf返回的不是原始數(shù)據(jù)類型,則會接著調(diào)用toString,如果toString返回的也不是原始數(shù)據(jù)類型,js會拋出一個異常,提示無法將引用類型轉(zhuǎn)換原始數(shù)據(jù)類型。

具體流程圖如下:

ToString

看個栗子🌰:

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return 'Hello,Teacher Cang!';
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return 12345;
 }
}
console.log(String(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了toString
Hello,Teacher Cang!

通過上面的代碼的運(yùn)行結(jié)果,我們得出這么一個結(jié)論:

在ToString情況下,toString的優(yōu)先級大于valueOf。

同樣我們看一下,toString返回的值不是原始數(shù)據(jù)類型時會怎樣:

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return {};
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return 'Hello,Teacher Cang!';
 }
}
console.log(String(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了toString
調(diào)用了valueOf
Hello,Teacher Cang!

根據(jù)運(yùn)行結(jié)果我們可以得出:

在ToString情況下,如果toString返回的不是原始數(shù)據(jù)類型,則會自動調(diào)用valueOf。

最后我們看一下極端情況,二者返回的都不是原始數(shù)據(jù)類型:

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return {};
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return {};
 }
}
console.log(String(obj)); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了toString
調(diào)用了valueOf
Uncaught TypeError: Cannot convert object to primitive value

我們又發(fā)現(xiàn):

在ToString情況下,如果toString和valueOf返回的都不是原始數(shù)據(jù)類型,那么js會拋出異常,提示無法將引用類型轉(zhuǎn)換原始數(shù)據(jù)類型。

我們將三個結(jié)論綜合一下:

在ToString情況下,js會優(yōu)先調(diào)用toString,如果toString返回的不是原始數(shù)據(jù)類型,則會接著調(diào)用valueOf,如果valueOf返回的也不是原始數(shù)據(jù)類型,js會拋出一個異常,提示無法將引用類型轉(zhuǎn)換原始數(shù)據(jù)類型。

具體流程圖如下:


“==”下的valueOf和toString的優(yōu)先級

從文章前面我們總結(jié)出來“==”的比較流程來看,引用類型轉(zhuǎn)換成原始數(shù)據(jù)類型之后,如果是Sting類型的話,還要再次轉(zhuǎn)成Number類型,因此“==”下的引用類型轉(zhuǎn)換原始數(shù)據(jù)類型過程中,遵循ToNumber的優(yōu)先級規(guī)則。

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return 'Hello,Teacher Cang!';
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return 12345;
 }
}
console.log(obj==12345); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了valueOf
true
const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return 12345;
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return {};
 }
}
console.log(obj==12345); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了valueOf
調(diào)用了toString
true
const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return {};
 },
 valueOf(){
  console.log('調(diào)用了valueOf');
  return {};
 }
}
console.log(obj==12345); 

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了toString
調(diào)用了valueOf
Uncaught TypeError: Cannot convert object to primitive value

“==”之外的類型轉(zhuǎn)換

“==”號只涉及到了ToPrimitive和ToNumber這兩種轉(zhuǎn)換,ToBoolean和ToString這兩個沒有涉及到的我們也介紹一下。

ToBoolean

對于ToBoolean,我們只需要記住幾個特例是轉(zhuǎn)成false的,其余的皆為true。

Boolean('') => false
Boolean(undefined) => false
Boolean(null) => false
Boolean(0) => false 

ToString

Number to String

Number轉(zhuǎn)String之前,首先會做一個去0和補(bǔ)0的操作,然后再去轉(zhuǎn)成String類型。

String(1.234) => "1.234"
String(NaN) => "NaN"
String(.1234) => "0.1234"
String(1.23400) => "1.234"

Boolean to String

String(true) => "true"
String(false) => "false"

null和undefined to String

String(null) => "null"
String(undefined) => "undefined"

引用類型 to String

引用類型先ToPrimitive轉(zhuǎn)換成原始數(shù)據(jù)類型,若轉(zhuǎn)換后的原始數(shù)據(jù)類型不是String類型,再做String類型的轉(zhuǎn)換。

const obj = {
 toString(){
  console.log('調(diào)用了toString');
  return true;
 }
}
console.log(String(obj))

控制臺輸出結(jié)果:
>>>>>>>>>>>>>>>>>>
調(diào)用了toString
"true"

總結(jié)

“==”下的類型轉(zhuǎn)換,要分為兩種情況來考慮。第一種,原始數(shù)據(jù)類型;第二種,引用類型。原始數(shù)據(jù)類型中String類型和Boolean類型是需要轉(zhuǎn)換成Number類型再去比較的,而引用類型則需要先轉(zhuǎn)換成原始數(shù)據(jù)類型再進(jìn)行后續(xù)的轉(zhuǎn)換。搞清整個流程之后,我們再去理解“==”涉及到的ToNumber和ToPrimitive是如何進(jìn)行轉(zhuǎn)換的。按照這樣子的理解步驟走,我們對“==”隱藏下的類型轉(zhuǎn)換會有比較清晰的認(rèn)識。另外,“==”不涉及到ToString和ToBoolean的類型轉(zhuǎn)換,在文章的后面部分我也加上去了,希望可以給小伙伴們一個更加全面的類型轉(zhuǎn)換的認(rèn)識。最后附上完整的“==”類型轉(zhuǎn)換的流程圖:

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • js獲取ip和地區(qū)

    js獲取ip和地區(qū)

    本文主要介紹了js獲取ip和地區(qū)的方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • javascript 可以拖動的DIV(二)

    javascript 可以拖動的DIV(二)

    關(guān)于這個實(shí)現(xiàn)div拖動的js函數(shù),實(shí)際上也是某位前輩公布于網(wǎng)上,這兒只是摘抄注解一下。
    2009-06-06
  • js重寫alert事件(避免alert彈框標(biāo)題出現(xiàn)網(wǎng)址)

    js重寫alert事件(避免alert彈框標(biāo)題出現(xiàn)網(wǎng)址)

    這篇文章主要給大家介紹了關(guān)于js重寫alert事件的相關(guān)資料,這樣可以避免alert彈框標(biāo)題出現(xiàn)網(wǎng)址的情況,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Bootstrap模態(tài)框使用詳解

    Bootstrap模態(tài)框使用詳解

    這篇文章主要為大家詳細(xì)介紹了Bootstrap模態(tài)框的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • layui 上傳文件_批量導(dǎo)入數(shù)據(jù)UI的方法

    layui 上傳文件_批量導(dǎo)入數(shù)據(jù)UI的方法

    今天小編就為大家分享一篇layui 上傳文件_批量導(dǎo)入數(shù)據(jù)UI的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • JavaScript面向?qū)ο蠛诵闹R與概念歸納整理

    JavaScript面向?qū)ο蠛诵闹R與概念歸納整理

    這篇文章主要介紹了JavaScript面向?qū)ο蠛诵闹R與概念,整理總結(jié)了JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)中基本概念、原理與操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • js實(shí)現(xiàn)簡單五子棋游戲

    js實(shí)現(xiàn)簡單五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡單五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • 基于JavaScript實(shí)現(xiàn)圖片預(yù)覽功能

    基于JavaScript實(shí)現(xiàn)圖片預(yù)覽功能

    在本文中,我們將學(xué)習(xí)如何使用 JavaScript 實(shí)現(xiàn)一個簡單的圖片預(yù)覽功能,我們將使用 HTML、CSS 和 JavaScript 來創(chuàng)建一個用戶界面,用戶可以輸入圖片 URL 并實(shí)時預(yù)覽圖片,感興趣的小伙伴跟著小編一起來看看吧
    2024-07-07
  • JavaScript實(shí)現(xiàn)大圖輪播效果

    JavaScript實(shí)現(xiàn)大圖輪播效果

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)大圖輪播效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 解析使用js判斷只能輸入數(shù)字、字母等驗(yàn)證的方法(總結(jié))

    解析使用js判斷只能輸入數(shù)字、字母等驗(yàn)證的方法(總結(jié))

    本篇文章對使用js判斷只能輸入數(shù)字、字母等驗(yàn)證的方法進(jìn)行了總結(jié)介紹,需要的朋友參考下
    2013-05-05

最新評論