js資料型別與隱式型別轉換

2022-05-23 17:06:10 字數 3871 閱讀 3729

執行環境是js中最為重要的乙個概念。執行環境定義了變數或函式有權訪問的其他資料,決定了它們各自的行為。每個執行環境都有乙個與之關聯的變數物件(variable object),環境中定義的所有變數和函式都儲存在這個物件中。雖然我們寫的**無法訪問這個物件,但解析器在處理資料時會在後台使用它。

全域性執行環境是最外圍的乙個執行環境。根據ecmascript實現所在的宿主環境不同,表示執行環境的物件也不一樣。在web瀏覽器中,全域性執行環境被認為是window物件,因此所有全域性變數和函式都是作為window物件的屬性和方法建立的。某個執行環境中的所有**執行完畢後,該環境被銷毀,儲存在其中的所有變數和函式定義也隨之銷毀(全域性執行環境直到應用程式退出---例如關閉網頁或瀏覽器時才會被銷毀)。

每個函式都有自己的執行環境。當執行流進入乙個函式時,函式的環境就會被推入乙個環境棧中。而在函式執行之後,棧將其環境彈出,把控制權返回給之前的執行環境。ecmascript程式中的執行例句正式由這個方便的機制控制這。

堆疊記憶體的釋放問題

堆記憶體:

堆記憶體的釋放只要沒有變數占用這個堆記憶體,瀏覽器就會在空閒的時候把它釋放掉,所以在專案中我們盡可能把不被使用的堆記憶體手動釋放掉。

棧記憶體:

函式執行會形成乙個私有的佔記憶體,一般函式執行完成,棧記憶體會自己釋放,除非棧記憶體中存在某乙個東西(例如:棧記憶體中開闢的堆記憶體)被棧記憶體意外的變數(或者是其他東西)占用了,此時的棧記憶體就不能被釋放掉;全域性作用域(棧記憶體)是在一開始載入js的時候誕生的,當前頁面關閉的時候會自動釋放掉。

js中的基礎資料型別,這些值都有固定的大小,往往都是儲存在記憶體空間中,由系統自動分配儲存空間。我們可以直接操作儲存在棧記憶體空間的值,因此基礎資料型別都是按值訪問

基礎資料型別:number string undefined boolean
由於引用資料型別儲存的值過於複雜(結構複雜即內容較多),渲染引擎會開闢乙個新的記憶體空間,單獨來儲存這些值,最後把記憶體空間引用位址賦值給對應的變數,後期所有的操作都是基於位址找到空間,然後對空間中的內容進行操作。

引用資料型別:object array date regexp math function
物件資料型別

開闢乙個記憶體空間(有乙個16進製制的位址)

把物件中的屬性名和屬性值一次儲存到記憶體空間中

把記憶體空間的位址賦值給變數

函式資料型別

開闢乙個記憶體空間(有乙個16進製制的位址)

把函式體中的**當作"字串"儲存到記憶體空間中

把記憶體空間位址賦值給變數

在前端面試中經常會遇到這樣乙個類似的題目

var a = 10;

var b = a;

b = 20;

// 這時a的值是多少?

在棧記憶體中的資料發生複製行為時,系統會自動為新的變數分配乙個新值。var b = a執行之後,a與b的值都等於10,但是他們其實已經是相互獨立互不影響的值了。

var a = ;

var b = a;

b.name = '小紅'

// 這時a.name的值是多少?

我們通過var b = a執行一次複製引用型別的操作。引用型別的複製同樣也會為新的變數自動分配乙個新的值儲存在棧記憶體中,但是不同的是,這個新的值,僅僅只是引用型別的乙個位址指標。當位址指標相同時,儘管他們相互獨立,但是在堆記憶體中訪問到的具體物件實際上是同乙個。

js中的資料型別是非常弱的,在使用算數運算子時,運算子兩邊的資料型別可以是任意的,比如,乙個字串可以和乙個數字相加。之所以不同的資料型別之間可以做運算,是因為js引擎在運算之前會悄悄地把他們進行了隱式型別轉換。

我們先來看機組典型的js中運算子操作結果

console.log( == ) // false

console.log( == !) // true

console.log( !== ) // true

console.log(nan != nan) // true

console.log(null == undefined) // true

console.log(null === undefined) // false

console.log(1 == true) // true

console.log(null > 0) // false

console.log(true + 1) // 2

console.log(undefined + 1) // nan

console.log({} + 1) // [object object]1

console.log( + {}) // [object object]

console.log([2,3] + [1,2]) // 2,31,2

原始值

轉化為值型別

轉化為字串

轉化為boolean

false

0"false"

false

true

1"true"

true00

"0"false11

"1"true

"0"0

"0"true

nannan

"nan"

false

infinity

infinity

"infinity"

true""0

""false

[ ]0

""true

[20]

20"20"

true

function(){}

nan"function(){}"

true

{}nan

"[object object]"

true

null

0"null"

false

undefined

nan"undefined"

false

js為我們提供了嚴格比較與型別轉換比較兩種模式,嚴格比較(===)只會在操作符兩側的操作物件型別一致,並且內容一致時才會返回true,否則返回false。而更為廣泛使用的==操作符則會首先將操作物件轉化為相同型別,在進行比較。

相等操作符會對操作值進行隱式轉換後進行比較:加法運算操作符:加法運算子在js中也用作字串拼接,所以加法操作符的規則分為兩種

邏輯操作符(!、&&、||)

邏輯非(!)操作符首先通過boolean()函式將它的操作值轉換為布林值,然後求反。

邏輯與(&&)操作符,如果乙個操作值不是布林值時,遵循以下規則進行轉換:

邏輯或(||)操作符,如果乙個操作值不是布林值,遵循以下規則:

關係操作符(, <=, >=)

與上述操作符一樣,關係操作符的操作值也可以是任意型別的,所以使用非數值型別參與比較時也需要系統進行隱式型別轉換:

js隱式型別轉換

筆試題 var x 1 if function console.log x 1undefined解析 if function f function f 作為表示式,function f消失,所以在if裡面,f為未宣告 任何乙個變數,未經宣告使用都會報錯。但是,typeof其時,不會報錯,而是unde...

JS隱式型別轉換

isnan 判斷引數是否為nan,返回boolean值,隱式呼叫顯示型別轉換中的number 再將呼叫的結果和nan比對,返回true false isnan 123s true 解析 number 123s nan nan nan isnan null false 解析 number null 0...

js隱式型別轉換

乙個沒有提供 symbol.toprimitive 屬性的物件,參與運算時的輸出結果 var obj1 console.log obj1 nan console.log object object console.log obj1 object object 接下面宣告乙個物件,手動賦予了 symb...