目錄
基本資料型態
引用資料類型
參數的傳遞方式
如何判斷資料型別
数据类型如何转换
变量提升与暂时性死区
声明全局变量
小結
首頁 web前端 js教程 JavaScript的資料型態與變數的解析(附範例)

JavaScript的資料型態與變數的解析(附範例)

Nov 15, 2018 pm 05:07 PM
javascript

這篇文章帶給大家的內容是關於JavaScript的資料型別與變數的解析(附範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

這篇文章,來聊聊 JS 中的資料型別與變數。這是在學習 JS 時最基礎的一類問題,但卻很重要。希望我的分享有幫助到你。

文章開頭,我先提幾個面試中遇到的問題:

例如:

#如何理解參數的按值傳遞?

什麼是暫時性死區?

什麼是變數提升?

全域變數和 window 的屬性有什麼差別?為什麼?

... ...

這篇文章的風格,在分析知識點的同時,插入一些我經歷過的面試題目。

基本資料型態

在 JS 中,基本資料型別有 6 種,分別是數值、字串、布林值、null、undefined、Symbol。

對於基本資料類型,我們需要明白的是:基本類型在記憶體中的儲存方式是堆疊。每一個數值都是單獨存放,互不影響。

基本類型都是按值存取的。在比較時,按值進行比較:

1 === 1 // true
登入後複製

引用資料類型

引用類型的值保存在堆疊中,而引用是保存在堆疊中。

引用類型按引用存取。在比較時,也比較的參考:

{} === {} // => false
登入後複製

參數的傳遞方式

在 JS 中,參數可以是任何類型的值,甚至可以是函數。

這裡要分析的是參數是以哪一種型別傳遞的?引用型別還是基本型別?

先看一個基礎的例子:

var out_num = 1;

function addOne(in_num) {
    in_num += 1;
    return in_num;
}

addOne(out_num); // => 2
out_num // => 1
登入後複製

這個例子中,我們給addOne() 函數傳遞一個實參out_num,這個時out_num 會傳遞給in_num,即內部存在著in_num = out_num 的過程。最後我們看到的結果是 out_num 並沒有被函數改變,說明 in_num 和 out_num 是兩個在記憶體中獨立存放的值,也就是按值傳遞。

再來看一個變形:

var out_obj = { value: 1 };

function addOne(in_obj) {
    in_obj.value += 1;
    return in_obj;
}

addOne(out_obj); // => { value: 2 }
out_obj // => { value: 2 }
登入後複製

問題來了?函數參數不是按值傳遞嗎?為什麼這裡函數內部的處理反映到外部了? 這是一個超級超級超級的理解迷思。

首先,我們還是得擺正觀點,也就是函數參數是按值傳遞的。 那這裡怎麼理解呢?對於引用型別而言,前面說引用型別分為引用和實際的記憶體空間。這裡 out_obj 依舊傳遞給 in_obj,即 in_obj = out_objout_obj 和 in_obj 是兩個引用,它們在記憶體中的儲存方式是獨立的,但是它們卻指向同一塊記憶體。

in_obj.value = 1 則是直接操作的實際物件。實際物件的改變,會同步到所有引用這個實際物件的引用。

JavaScript的資料型態與變數的解析(附範例)

JavaScript的資料型態與變數的解析(附範例)

你再來看這個例子,或許會更清楚一些。

var out_obj = { value: 1 };

function addOne(in_obj) {
    in_obj = { value: 2 };
    return in_obj;
}

addOne(out_obj); // => { value: 2 }
out_obj // => { value: 1 }
登入後複製

你只要抓住一點:物件的賦值就會造成引用指向的實際物件改變。

如何判斷資料型別

判斷資料型別,通常有三種具體的方法:

1、typeof 運算子

typeof 操作符傳回一個表示資料類型的字串。它有以下明顯的缺陷:

typeof null // => 'object'

typeof [] // => 'object'
登入後複製

這是因為在 JS 語言設計之初遺留的 bug。可以閱讀這篇文章 http://2ality.com/2013/10/typ... 了解更多關於 typeof 處理 null 的問題。

所以 typeof 最好用來判斷一些基本類型,像是數值、字串、布林值、undefined、Symbol。

2、instanceof 運算子

typeof  的背後是透過判斷type tags 來判斷資料類型,而instanceof 則是透過判斷建構函數的prototype 是否出現在物件原型鏈上的任何位置。

舉例:

{} instanceof Object // => true

[] instanceof Array // => true
[] instanceof Object // => true
登入後複製

也判斷自訂類型:

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var auto = new Car('Honda', 'Accord', 1998);

console.log(auto instanceof Car);
// => true

console.log(auto instanceof Object);
// => true
登入後複製

所以,對於字面量形式的基本資料類型,不能透過instanceof 來判斷:

1 instanceof Number // => false

Number(1) instanceof Number // => false

new Number(1) instanceof Number // => true
登入後複製

3、Object.prototype.toString()

這是目前最推薦的一種方法,可以更精細且準確的判斷任何資料類型,甚至是JSON、正規、日期、錯誤等等。在 Lodash 中,其判斷資料型別的核心也是 Object.prototype.toString() 方法。

Object.prototype.toString.call(JSON) // => "[object JSON]"
登入後複製

關於這背後的原理,你可以閱讀這篇文章http://www.cnblogs.com/ziyunf...

4、其他

上面三種是通用的判斷資料類型的方法。面試中也會出現如何判斷一個陣列、如何判斷 NaN、如何判斷類別陣列物件、如何判斷一個空物件等問題。這一類問題比較開放,解決想法通常是抓住判斷資料的核心特徵。

舉個例子:判斷類別數組物件。

你先要知道 JS 中类数组对象是什么样子的,并寻求一个实际的参照物,比如 arguments 就是类数组对象。那么类数组对象具有的特点是:真值 & 对象 & 具有 length 属性 & length 为整数 & length 的范围大于等于 0,小于等于最大安全正整数(Number.MAX_SAFE_INTEGER)。

在你分析特点的时候,答案就呼之欲出了。【注意全面性】

数据类型如何转换

JS 数据类型的动态性将贯穿整个 JS 的学习,这是 JS 非常重要的特性,很多现象就是因为动态性的存在而成为 JS 独有。

正是由于动态性,JS 的数据类型可能在你毫无察觉的情况下,就发生了改变,直到运行时报错。

这里主要分析下面 8 种转换规则。

1、if 语句

if 语句中的类型转换是最常见的。

if (isTrue) {
    // ...
} else {}
登入後複製

在 if 语句中,会自动调用 Boolean() 转型函数对变量 isTrue 进行转换。

当 isTrue 的值是 null, undefined, 0, NaN, '' 时,都会转为 false。其余值除 false 本身外都会转为 true。

2、Number() 转型函数

我们重点关注 null undefined 以及字符串在 Number() 下的转换:

Number(null) // => 0
Number(undefined) // => NaN
Number('') // => 0
Number('123') // => 123
Number('123abc') // => NaN
登入後複製

注意和 parseInt() 对比。

3、parseInt()

parseInt(null) // => NaN
parseInt(undefined) // => NaN
parseInt('') // => NaN
parseInt('123') // => 123
parseInt('123abc') // => 123
登入後複製

4、==

这里需要注意的是:

null == undefined // => true

null == 0 // => false
undefined == false // => false
登入後複製

null 与 undefined 的相等性是由 ECMA-262 规定的,并且 null 与 undefined 在比较相等性时不能转换为其他任何值。

5、关系操作符

对于两个字符串的比较,是比较的字符编码值:

'B'  true
登入後複製

一个数值,另一个其他类型,都将转为数字进行比较。

两个布尔值转为数值进行比较。

对象,先调用 valueOf(),若不存在该方法,则调用 toString()。

6、加法

加法中特别注意的是,数字和字符串相加,将数字转为字符串。

'1' + 2 => // '12'
1 + 2 => // 3
登入後複製

对于对象和布尔值,调用它们的 toString() 方法得到对应的字符串值,然后进行字符串相加。对于 undefined 和 null 调用 String() 取得字符串 'undeifned' 和 'null'。

{ value: 1 } + true // => "[object Object]true"
登入後複製

7、减法

对于字符串、布尔值、null 或者 undefined,自动调用 Number(),转换结果若为 NaN,那么最终结果为 NaN。

对于对象,先调用 valueOf(),如果得到 NaN,结果为 NaN。如果没有 valueOf(),则调用 toString()。

8、乘法、除法

对于非数值,都会调用 Number() 转型函数。

变量提升与暂时性死区

JS 中有三种声明变量的方式:var, let, const。

var 声明变量最大的一个特点是存在变量提升。

console.log(a); // undefined
var a = 1;
console.log(a); // 1
登入後複製

第一个打印结果表示,在声明变量 a 之前,a 就已经可以访问了,只不过并未赋值。这就是变量提升现象。(具体原因,我放在后面分析作用域的时候来写)

let 和 const 就不存在这个问题,但是又引入了暂时性死区这样的概念。

/**
* 这上面都属于变量 a 的暂时性死区
* console.log(a) // => Reference Error
*/
let a = 1;
console.log(a); // => 1
登入後複製

即声明 a 之前,不能够访问 a,而直接报错。

而暂时性死区的出现又引出另外一个问题,即 typeof 不再安全。你可以参考这篇文章 http://es-discourse.com/t/why...

补充:一个经典面试题

for (var i = 0; i <p>我先不再这里展开分析,我打算放到异步与事件循环机制中去分析。不过这里将 var 替换成 let 可以作为一种解决方案。如果你有兴趣,也可以先去分析。</p><p>对于 const,这里再补充一点,用于加深对基本类型和引用类型的理解。</p><pre class="brush:php;toolbar:false">const a = 1;
const b = { value: 1 };

a = 2; // => Error
b.value = 2; // => 2
b = { value: 2 }; // => Error
登入後複製

本质上,const 并不是保证变量的值不得改动,而是变量指向的内存地址不得改动。

声明全局变量

直接通过 var 声明全局变量,这个全局变量会作为 window 对象的一个属性。

var a = 1;
window.a // => 1
登入後複製

在这里提出两个问题,一是 let 声明的全局变量会成为 window 的属性吗?二是 var 声明的全局变量和直接在 window 创建属性有没有区别?

先来回答第一问题。let 声明的全局变量不会成为 window 的属性。用什么来支撑这样的结论呢?在 ES6 中,对于 let 和 const 声明的变量从一开始就形成封闭作用域。想想之前的暂时性死区。

第二个问题,var 声明的全局变量和直接在 window 创建属性存在着本质的区别。先看下面的代码:

var a = 1;
window.a // => 1

window.b = 2;

delete window.a
delete window.b

window.a // => 1
window.b // => undefined
登入後複製

我们可以看到,直接创建在 window 上的属性可以被 delete 删除,而 var 创建的全局属性则不会。这是现象,通过现象看本质,二者本质上的区别在于:

使用 var 宣告的全域變數的 [[configurable]] 資料屬性的值為 false,不能透過 delete 刪除。而直接在物件上建立的屬性預設 [[configurable]] 的值為 true,即可以被 delete 刪除。 (關於[[configurable]] 屬性,在後面的文章中分析物件的時候還會提到)

小結

在這篇「資料類型與變量」文章中,分析了7 個大類。再來回顧一下:

基本型別、參考型別、參數傳遞方式、如何判斷資料型別、資料型別轉換、變數提升與暫時性死區、宣告全域變數。

這些不僅是校招面試中的高頻考點,也是學習 JS 必不可少的知識點。

Tip1:《JavaScript 高階程式設計》這本書被稱為「前端的聖經」是有原因的。對於正在準備校園招募的你,非常有必要! 書讀百遍,其義自見。 你會發現你在面試中遇到的絕大部分 JS 相關的知識點都能在這本書中找到「答案」!

Tip2:在準備複習的過程中,注意知識的模組性與相關性。你得有自己劃分知識模組的能力,例如今天的「資料類型與變數」模組。相關性是指,任何的知識都是由連結的,例如這裡牽涉到作用域、記憶體等模組。

#

以上是JavaScript的資料型態與變數的解析(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles