iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 4
2
Modern Web

JavaScript基本功修煉系列 第 4

JavaScript基本功修練:Day4 - 基本型別(II) - 字串、布林、null、undefined、Symbol

  • 分享至 

  • xImage
  •  

延續上文關於JavaScript基本型別的內容,這篇主要講解字串(string)、布林值(boolean)、nullundefined和Symbol(ES6新增)。

字串(string)

字串就是文字。例如是'Hello World''JavaScript基本功修煉''12345'等等。12345雖然本來是數字,但放在引號''裏就會成為了字串。

我們可以單引號''、雙引號""、重音符``把字串括著:

//單引號
var singleQuote = 'JavaScript好難!'
//雙引號
var doubleQuote = "JavaScript好難!"
//重音符
var backtick = `JavaScript好難!`

注意,這些引號都不能混合使用,例如'12345",這樣做會報錯。

剛學JS幾星期後,我開始轉用重音符的寫法,因為它比較方便寫和閱讀,至此人生又少了點坎坷

具體的好處:

  1. 重音符的寫法可以斷行
var fruit = `Fruit:
1. apple
2. orange
3. cherry
4. banana
`

單或雙引號就不能斷行,這樣會報錯:

var fruit = "Fruit:
1. apple
2. orange
3. cherry
4. banana
"
console.log(fruit); //Uncaught SyntaxError: Invalid or unexpected token
  1. 連接字串時可用${}
var discount = 0.7
var fries = 15
console.log(`今天薯條的售價是${fries * discount}元`);

你可能會認為這個簡單例子其實用單或雙引號也可以,就像這樣:

console.log('今天薯條的售價是' + fries * discount + '元')

這個寫法也行的。但是,如果今天的情況是要組合一大堆字串,而非單單一句,那麼我們在輸入和組合字串的時候,就要很耗時地去找出哪裏要分開,哪裏要加上引號和加號。例如我們要組合一個HTML字串時:

${}去寫:

//計算打折後的價錢
function discount(oldPrice){
    return oldPrice * 0.7 
}

var price1 = `
<h2>今天的特價貨品:</h2>
<ul>
    <li>薯片:$${discount(20)},原價$20</li>
    <li>漢堡:$${discount(30)},原價$30</li>
</ul>
`

''""去寫:

var price2 = 
'<h2>今天的特價貨品:</h2>' + '<ul><li>薯片:$' + discount(20) + ',原價$20</li><li>漢堡:$' + discount(30) + ',原價$30</li></ul>'

雖然回傳的結果是一樣(只差在是逼在一行還是整齊地斷行),但用``去寫,除了不用去想哪裏要下+'',也可以像寫HTML一樣去寫,寫法一目了然!

特別文字、跳脫符號

使用特別文字的情況的例子:

  • (在程式碼中)斷行
  • 產生特別字符,例如emoji、© 等等

(在程式碼中)斷行

剛才提及單或雙引號是不能斷行,但如果加上跳脫符號\n或者\,也是可以實現的。

var fruit1 = 'Fruit:\n1. apple\n2. orange\n3. cherry\n4. banana'

這樣寫的話,console會以斷行顯示。

var fruit3 = 'Fruit: \
1. apple \
2. orange \
3. cherry \
4. banana'

注意,\後面不能輸入空白或其他字元。

然而這個寫法在console顯示回傳時仍是以一行顯示,並沒有斷行。所以這個寫法只是讓你在寫程式碼時,合法地在單引號或雙引號裏按enter去斷行。

其實這些字串被渲染到網頁上時,一併都是以一行顯示,所以這個微小的分別只是在查console時會碰到。

其他運用例子:
當字串裏包含了單引號,就不能用單引號去包著字串。我們可以轉用雙引號或加入\作分隔。

console.log('Tom's car') //報錯
console.log("Tom's car")   
console.log('Tom\'s car')

特別字符

console.log('\u00AE') //®
console.log('\u{1F606}') // ?

布林(boolean)

布林值就是truefalse,非常簡單。

5 == 7 //false
undefined === null //false
2 > 1 //true

通常布林值會配搭邏輯運算子||(or)、&&(and)、!(not)使用。之後的文章會談到。

falsy與truthy

  • 所有的值都可以被轉為布林值,並分為falsytruthy兩大類。
  • 如果該值被轉為布林值後的結果是false,它就是屬於falsy類別,相反,true就是屬於truthy類別。
  • 我們可以用Boolean(value)去把值轉型為布林值。

false (falsy):
0,null,undefined,NaN,""

true(truthy):
除了以上的值都是。

以下的例子要格外注意:

Boolean('0') //true。'0'是一個字串,只要不是空字串就會回傳true
Boolean('') //false
Boolean(' ') //true。這不是一個空字串,所以回傳true

null 與 undefined

null = 「沒有值」的值
undefined = 沒有被賦予任何值(不論有沒有宣告變數)

  • 當一個變數沒有被賦予任何值,JavaScript會自動賦予undefined但JavaScript不會自動賦予null給變數,那必然是由你自己動手去賦予
  • nullundefined都是falsy
  • null的型別是object,但undefined的型別是undefined
  • null == undefined //true,因為它們都是falsy
  • null === undefined //false。嚴謹模式會比較兩者的型別。nullobject,但undefinedundefined

Symbol

ES6新增了Symbol這個基本型別。根據MDN的解釋,它雖然也有其他用法,但最主要是用在物件裏的屬性。

A symbol value may be used as an identifier for object properties; this is the data type's primary purpose

Symbol的特性

  • Symbol最大的用處是它可以是獨一無二的。以下例子可見,即使xy都是Symbol(),它們卻不相等。
const x = Symbol();
const y = Symbol();

console.log(x === y) //false 

Symbol的語法

  • Symbol沒有縮寫語法,不像字串一樣能夠用縮寫``""。用Symbol時一定要寫成Symbol()
  • Symbol()後面的那個()只是用作寫下一些關於這個Symbol的描述,並沒有實際作用。例如:Symbol("person")Symbol("age")。方便我們看到多個Symbol()時,可以一眼看出()裏的描述,幫助自己更快區分到它們,也有助於除錯。

Symbol屬性較隱蔽

Symbol()其中一個優勢是它並不明顯,第三方不能用某些語法去查詢到這個屬性,例如Object.keys(user)

const id = Symbol("id")

let user = {
    name: 'Tom',
    age: 23,
    birthday: 'Aug 11',
    id: 111,
    [id]: 222
}

console.log(Object.keys(user)) //["name", "age", "birthday", "id"]

for...in

for (let key in user) console.log(key);
// name
// age
// birthday
// id

然而,Object.assgin()卻可以查看到,因為這個語法原意是把所有屬性都複製起來,而Symbol()也會被複製到。此外,Object.getOwnPropertySymbols()也能針對找出Symbol()屬性。

Symbol的應用例子

避免因為鍵值相同,使較新的屬性覆蓋掉較舊的屬性。

let user = {
    name: 'Tom',
    age: 23,
    birthday: 'Aug 11',
    id: 111
}

//覆蓋掉user的本身的id
user.id = 222;

以上這個例子可以想像成user這個物件是來自第三方的程式碼,裏面雖然也有id這個屬性,但我這邊也想建立一個id的屬性作為其他用途,可是又不能蓋掉之前的id,所以這個例子可以用Symbol()

let user = {
    name: 'Tom',
    age: 23,
    birthday: 'Aug 11',
    id: 111
}

//確保不會蓋掉之前的屬性
const id = Symbol("id")
user[id] = 222

更直接的寫法:

const id = Symbol("id")

let user = {
    name: 'Tom',
    age: 23,
    birthday: 'Aug 11',
    id: 111,
    [id]: 222
}

注意,鍵值需要用[]包起來,沒有用[]的話,鍵值會變成字串型別,直接蓋掉了原本的id

倒過來想,如果我們想避免自己建立的屬性被第三方開發者蓋掉,我們也可以自己用Symbol()去建立屬性。此外,使用Symbol()也能避免第三方輕易查看到該屬性。

Symbol值也可以相等?

雖然Symbol的主要賣點是獨特的存在,但如果我們想在程式碼某個地方,再次使用同一個Symbol值,就可以用Symbol.for()的方法。

Symbol.for()可以把當在()裏的字串當作是參數,例如執行Symbol.for("cat")時,JavaScript會查看有沒有"cat"作為參數的Symbol值,如果有,就返回這個值,如沒有,就去建立一個,把它注冊成為全域的Symbol。

以下的例子可見,ididAgain是指向同一個Symbol值:

let id = Symbol.for("id");
let idAgain = Symbol.for("id");

console.log(id === idAgain) //true

如果我調用Symbol("id")Symbol.for("id")各30次,Symbol("id")會返回30個不同的Symbol值,但Symbol.for("id")30次都是返回同一個Symbol值。

總結

字串:

  • 可用''""``括住
  • 使用''""包字串時不能斷行
  • 建議使用``,連接字串時使用${},這樣較方便和易讀

布林值:

  • truefalse
  • 0,null,undefined,NaN,""falsy,其餘都是truthy
  • 可以用Boolean()去把值轉為布林值

nullundefined:

  • null是「沒有值」的值,undefined是指沒有被賦予任何值
  • nullundefined都是falsy
  • null的型別是object,但undefined的型別是undefined

Symbol()

  • Symbol()是獨一無二的
  • Symbol()主要用途是避免蓋掉物件裏的其他屬性
  • Symbol()的屬性較隱蔽,但不代表不能被查詢
  • 可用Symbol.for()返回同一個symbol值

參考資料

JAVASCRIPT.INFO - String
JAVASCRIPT.INFO - Data Types
undefined 和 null 的差別

Symbol:
JAVASCRIPT.INFO - Symbol
ECMAScript 6 入门
The Complete Guide to JS Symbols ES6


上一篇
JavaScript基本功修練:Day3 - 基本型別(I) - 數字
下一篇
JavaScript基本功修練:Day5 - 宣告變數 - let、const、var
系列文
JavaScript基本功修煉31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言