成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

從[]==![]為true來剖析JavaScript各種蛋疼的類型轉(zhuǎn)換

Jeff / 1345人閱讀

摘要:將他們放在堆中是為了不影響棧的效率。所以簡單數(shù)據(jù)類型的值直接存放在棧中。可以對比上面那張圖默認(rèn)是調(diào)用方法的依,于是等于空字符串。空字符串中國標(biāo)準(zhǔn)時間方法返回對象的原始值,可能是字符串?dāng)?shù)值或值等,看具體的對象。,需要兩個操作數(shù)同時轉(zhuǎn)為。

你是否在面試中遇到過各種奇葩和比較細(xì)節(jié)的問題?

[]==[]
//false
[]==![]
//true
{}==!{}
//false
{}==![]
//VM1896:1 Uncaught SyntaxError: Unexpected token ==
![]=={}
//false
[]==!{}
//true
undefined==null
//true

看了這種題目,是不是想抽面試官幾耳光呢?哈哈,是不是看了之后一臉懵逼,兩臉茫然呢?心想這什么玩意

其實這些都是紙老虎,知道原理和轉(zhuǎn)換規(guī)則,理解明白這些很容易的,炒雞容易的,真的一點都不難,我們要打到一切紙老虎,不信?


我們就從[] == []和[] == ![]例子切入分析一下為什么輸出的結(jié)果是true而不是其它的呢?

[]==[]為什么是false?

有點js基礎(chǔ)應(yīng)該知道對象是引用類型,就會一眼看出來[] == []會輸出false,因為左邊的[]和右邊的[]看起來長的一樣,但是他們引用的地址并不同,這個是同一類型的比較,所以相對沒那么麻煩,暫時不理解[] == []為false的童鞋這里就不細(xì)說,想要弄清楚可以通過這篇文章來了解JavaScript的內(nèi)存空間詳解.

前端基礎(chǔ)進階(一):內(nèi)存空間詳細(xì)圖解

變量對象與堆內(nèi)存

簡單類型都放在棧(stack)里
對象類型都放在堆(heap)里
var a = 20;
var b = "abc";
var c = true;
var d = { m: 20 }//地址假設(shè)為0x0012ff7c
var e = { m: 20 }//重新開辟一段內(nèi)存空間假設(shè)為0x0012ff8f
console.log(e==d);//false
那為什么引用值要放在堆中,而原始值要放在棧中,不都是在內(nèi)存中嗎,為什么不放在一起呢?那接下來,讓我們來探索問題的答案!(扯遠(yuǎn)了)

首先,我們來看一下代碼:

function Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age;
}
var num = 10;
var bol = true;
var str = "abc";
var obj = new Object();
var arr = ["a","b","c"];
var person = new Person(100,"笨蛋的座右銘",25); 

然后我們來看一下內(nèi)存分析圖:

`變量num,bol,str為基本數(shù)據(jù)類型,它們的值,直接存放在棧中,obj,person,arr為復(fù)合數(shù)據(jù)類型,他們的引用變量存儲在棧中,指向于存儲在堆中的實際對象。
由上圖可知,我們無法直接操縱堆中的數(shù)據(jù),也就是說我們無法直接操縱對象,但我們可以通過棧中對對象的引用來操作對象,就像我們通過遙控機操作電視機一樣,區(qū)別在于這個電視機本身并沒有控制按鈕。
`

現(xiàn)在讓我們來回答為什么引用值要放在堆中,而原始值要放在棧中的問題:

`記住一句話:能量是守衡的,無非是時間換空間,空間換時間的問題
堆比棧大,棧比堆的運算速度快,對象是一個復(fù)雜的結(jié)構(gòu),并且可以自由擴展,如:數(shù)組可以無限擴充,對象可以自由添加屬性。將他們放在堆中是為了不影響棧的效率。而是通過引用的方式查找到堆中的實際對象再進行操作。相對于簡單數(shù)據(jù)類型而言,簡單數(shù)據(jù)類型就比較穩(wěn)定,并且它只占據(jù)很小的內(nèi)存。不將簡單數(shù)據(jù)類型放在堆是因為通過引用到堆中查找實際對象是要花費時間的,而這個綜合成本遠(yuǎn)大于直接從棧中取得實際值的成本。所以簡單數(shù)據(jù)類型的值直接存放在棧中。`

搬運文章:理解js內(nèi)存分配

知道的大神當(dāng)然可以飄過,這里主要給計算機基礎(chǔ)薄弱的童鞋補一下課.

[]==![]為什么是true?

首先第一步:你要明白ECMAScript規(guī)范里面==的真正含義

GetValue 會獲取一個子表達式的值(消除掉左值引用),在表達式 [] == ![] 中,[] 的結(jié)果就是一個空數(shù)組的引用(上文已經(jīng)介紹到數(shù)組是引用類型),而 ![] 就有意思了,它會按照 11.4.9 和 9.2 節(jié)的要求得到 false。

首先我們了解一下運算符的優(yōu)先級:

剛看到這里是不是就咬牙切齒了,好戲還在后頭呢,哈哈

!取反運算符的優(yōu)先級會高于==,所以我們先看看!在ECAMScript是怎么定義的?

所以![]最后會是一個Boolean類型的值(這點很關(guān)鍵,涉及到下面的匹配選擇).

兩者比較的行為在 11.9.3 節(jié)里,所以翻到 11.9.3:

在這段算法里,[]是Object,![]是Boolean,兩者的類型不同,y是Boolean類型,由此可知[] == ![]匹配的是條件 8,所以會遞歸地調(diào)用[] == ToNumber(Boolean)進行比較。

[]空數(shù)組轉(zhuǎn)化成Boolean,那么這個結(jié)果到底是true還是false呢,這個當(dāng)然不是你說了算,也不是我說了算,ECMAScript定義的規(guī)范說了算:我們來看看規(guī)范:

[]是一個對象,所以對應(yīng)轉(zhuǎn)換成Boolean對象的值為true;那么![]對應(yīng)的Boolean值就是false
進而就成了比較[] == ToNumber(false)

再來看看ECMAScipt規(guī)范中對于Number的轉(zhuǎn)換

由此可以得出此時的比較成了[]==0;

在此處因為 [] 是對象,0是數(shù)字Number,比較過程走分支 10(若Type(x)為Object且Type(y)為String或Number, 返回比較ToPrimitive(x) == y的結(jié)果。),可以對比上面那張圖.

ToPrimitive 默認(rèn)是調(diào)用 toString 方法的(依 8.2.8),于是 ToPrimitice([]) 等于空字符串。

再來看看ECMAScript標(biāo)準(zhǔn)怎么定義ToPrimitice方法的:

是不是看了這個定義,還是一臉懵逼,ToPrimitive這尼瑪什么玩意啊?這不是等于沒說嗎?

再來看看火狐MDN上面文檔的介紹:
JS::ToPrimitive

查了一下資料,上面要說的可以概括成:

ToPrimitive(obj,preferredType)

JS引擎內(nèi)部轉(zhuǎn)換為原始值ToPrimitive(obj,preferredType)函數(shù)接受兩個參數(shù),第一個obj為被轉(zhuǎn)換的對象,第二個
preferredType為希望轉(zhuǎn)換成的類型(默認(rèn)為空,接受的值為Number或String)

在執(zhí)行ToPrimitive(obj,preferredType)時如果第二個參數(shù)為空并且obj為Date的事例時,此時preferredType會
被設(shè)置為String,其他情況下preferredType都會被設(shè)置為Number如果preferredType為Number,ToPrimitive執(zhí)
行過程如
下:
1. 如果obj為原始值,直接返回;
2. 否則調(diào)用 obj.valueOf(),如果執(zhí)行結(jié)果是原始值,返回之;
3. 否則調(diào)用 obj.toString(),如果執(zhí)行結(jié)果是原始值,返回之;
4. 否則拋異常。

如果preferredType為String,將上面的第2步和第3步調(diào)換,即:
1. 如果obj為原始值,直接返回;
2. 否則調(diào)用 obj.toString(),如果執(zhí)行結(jié)果是原始值,返回之;
3. 否則調(diào)用 obj.valueOf(),如果執(zhí)行結(jié)果是原始值,返回之;
4. 否則拋異常。

首先我們要明白obj.valueOf()obj.toString()還有原始值分別是什么意思,這是弄懂上面描述的前提之一:

toString用來返回對象的字符串表示。

var obj = {};
console.log(obj.toString());//[object Object]

var arr2 = [];
console.log(arr2.toString());//""空字符串
  
var date = new Date();
console.log(date.toString());//Sun Feb 28 2016 13:40:36 GMT+0800 (中國標(biāo)準(zhǔn)時間)

valueOf方法返回對象的原始值,可能是字符串、數(shù)值或bool值等,看具體的對象。

var obj = {
  name: "obj"
};
console.log(obj.valueOf());//Object {name: "obj"}

var arr1 = [1];
console.log(arr1.valueOf());//[1]



var date = new Date();
console.log(date.valueOf());//1456638436303
如代碼所示,三個不同的對象實例調(diào)用valueOf返回不同的數(shù)據(jù)

**原始值指的是["Null","Undefined","String","Boolean","Number"]五種基本數(shù)據(jù)類型之一(我猜的,查了一下
確實是這樣的)**

弄清楚這些以后,舉個簡單的例子:

var a={};
ToPrimitive(a)

分析:a是對象類型但不是Date實例對象,所以preferredType默認(rèn)是Number,先調(diào)用a.valueOf()不是原始值,繼續(xù)來調(diào)
用a.toString()得到string字符串,此時為原始值,返回之.所以最后ToPrimitive(a)得到就是"[object Object]".

如果覺得描述還不好明白,一大堆描述晦澀又難懂,我們用代碼說話:

const toPrimitive = (obj, preferredType="Number") => {
    let Utils = {
        typeOf: function(obj) {
            return Object.prototype.toString.call(obj).slice(8, -1);
        },
        isPrimitive: function(obj) {
            let types = ["Null", "String", "Boolean", "Undefined", "Number"];
            return types.indexOf(this.typeOf(obj)) !== -1;
        }
    };
   
    if (Utils.isPrimitive(obj)) {
        return obj;
    }
    
    preferredType = (preferredType === "String" || Utils.typeOf(obj) === "Date") ?
     "String" : "Number";

    if (preferredType === "Number") {
        if (Utils.isPrimitive(obj.valueOf())) {
            return obj.valueOf()
        };
        if (Utils.isPrimitive(obj.toString())) {
            return obj.toString()
        };
    } else {
        if (Utils.isPrimitive(obj.toString())) {
            return obj.toString()
        };
        if (Utils.isPrimitive(obj.valueOf())) {
            return obj.valueOf()
        };
    }
}

var a={};
ToPrimitive(a);//"[object Object]",與上面文字分析的一致

分析了這么多,剛才分析到哪里了,好像到了比較ToPrimitive([]) == 0現(xiàn)在我們知道ToPrimitive([])="",也就是空字符串;

那么最后就變成了""==0這種狀態(tài),繼續(xù)看和比較這張圖

發(fā)現(xiàn)typeof("")為string,0為number,發(fā)現(xiàn)第5條滿足規(guī)則,最后就成了toNumber("")==0的比較了,根據(jù)toNumber的轉(zhuǎn)換規(guī)則:

所以toNumber("")=0,最后也就成了0 == 0的問題,于是[]==![]最后成了0 == 0的問題,答案顯而易見為true,一波三折

最后總結(jié)一下

==運算規(guī)則的圖形化表示

前面說得很亂,根據(jù)我們得到的最終的圖3,我們總結(jié)一下==運算的規(guī)則:

1. undefined == null,結(jié)果是true。且它倆與所有其他值比較的結(jié)果都是false。

2. String == Boolean,需要兩個操作數(shù)同時轉(zhuǎn)為Number。

3. String/Boolean == Number,需要String/Boolean轉(zhuǎn)為Number。

4. Object == Primitive,需要Object轉(zhuǎn)為Primitive(具體通過valueOf和toString方法)。

瞧見沒有,一共只有4條規(guī)則!是不是很清晰、很簡單。
主要參考文章和文獻

ECMAScript5.1規(guī)范中文版

通過一張簡單的圖,讓你徹底地、永久地搞懂JS的==運算

JavaScript中加號運算符的類型轉(zhuǎn)換優(yōu)先級是什么?

喜歡我總結(jié)的文章對你有幫助有收獲的話麻煩點個star
我的github博客地址,總結(jié)的第一篇,不好之處和借鑒不得到之處還望見諒,您的支持就是我的動力!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://hztianpu.com/yun/81645.html

相關(guān)文章

  • js技術(shù) - 收藏集 - 掘金

    摘要:還記得剛開始學(xué)習(xí)的時候,內(nèi)存管理前端掘金作為一門高級語言,并不像低級語言那樣擁有對內(nèi)存的完全掌控。第三方庫的行代碼內(nèi)實現(xiàn)一個前端掘金前言本文會教你如何在行代碼內(nèi),不依賴任何第三方的庫,用純實現(xiàn)一個。 (譯) 如何使用 JavaScript 構(gòu)建響應(yīng)式引擎 —— Part 1:可觀察的對象 - 掘金原文地址:How to build a reactive engine in JavaSc...

    Guakin_Huang 評論0 收藏0
  • js技術(shù) - 收藏集 - 掘金

    摘要:還記得剛開始學(xué)習(xí)的時候,內(nèi)存管理前端掘金作為一門高級語言,并不像低級語言那樣擁有對內(nèi)存的完全掌控。第三方庫的行代碼內(nèi)實現(xiàn)一個前端掘金前言本文會教你如何在行代碼內(nèi),不依賴任何第三方的庫,用純實現(xiàn)一個。 (譯) 如何使用 JavaScript 構(gòu)建響應(yīng)式引擎 —— Part 1:可觀察的對象 - 掘金原文地址:How to build a reactive engine in JavaSc...

    zhou_you 評論0 收藏0
  • js中抽象相等==

    摘要:中抽象相等比較算法大致介紹一下的數(shù)據(jù)類型的數(shù)據(jù)類型分為種如果再加上數(shù)據(jù)類型,一共種與的區(qū)別描述一個空值空的對象引用即空指針,被當(dāng)做一個對象,輸出為算是一個吧,輸出為。運算符把其值參數(shù)轉(zhuǎn)換為非類型對象。 Javascript中抽象相等比較算法 undefined==null //true []==[] //false []==![] //true {}==!{} //false ![]=...

    hzx 評論0 收藏0
  • 吹毛求疵的追求優(yōu)雅高性能JavaScript

    摘要:這樣優(yōu)化后我們最多進行次判斷即可,大大提高了代碼的性能。表達式的值具有離散性, 個人博客,點擊查看目錄,喜歡可以關(guān)注一下. 1.從[]==![]為true來剖析JavaScript各種蛋疼的類型轉(zhuǎn)換 2.吹毛求疵的追求優(yōu)雅高性能JavaScript 李小龍說過:天下武功,無堅不摧,唯快不破.(真的說過嗎?)我想說的是:世間網(wǎng)站,完美體驗,唯快不破.(這個我承認(rèn)我說過.) showImg...

    saucxs 評論0 收藏0
  • 也談JavaScript數(shù)組去重

    摘要:昨天在微博上看到一篇文章,也寫數(shù)組去重,主要推崇的方法是將利用數(shù)組元素當(dāng)作對象來去重。我在微博轉(zhuǎn)發(fā)了用對象去重不是個好辦法然后作者問什么才是推薦的方法。實例對象實例對象主要指通過構(gòu)造函數(shù)類生成的對象。 本文同時發(fā)布于個人博客https://www.toobug.net/articl... JavaScript的數(shù)組去重是一個老生常談的話題了。隨便搜一搜就能找到非常多不同版本的解法。 昨...

    崔曉明 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<