[Rails] 分辨 symbol 和 string

遇到 Ruby 語法上,冒號 + 變數

routes.rb
1
2
3
4
5
resources :products do
member do
post :add_to_cart
end
end

products 就叫做 symbol

什麼是 Symbol?

翻譯上,符號象徵
可以直接說是,不可改變的字串

在 JS 世界,是宣告一個 name 的 obj,再把字串丟進 name

test.js
1
var name = 'jimmy'

在 Ruby 的世界也是做一樣的事,但我們來一窺究竟底層

終端機上,打開 irb

$irb
1
2
3
4
5
6
7
8
2.3.1 :001 > Symbol.all_symbols.count
=> 11064
2.3.1 :002 > who_name_is = "Jimmy"
=> "Jimmy"
2.3.1 :003 > Symbol.all_symbols.count
=> 11065
2.3.1 :006 > Symbol.all_symbols.map(&:to_s).include?("who_name_is")
=> true

上述定義全新的變數 who_name_is
可以看到,在 Symbol 的總數多了一筆!!!

意味著宣告一個全新的變數,Ruby 會偷偷替 symbol 建立一筆資料

$irb
1
2
3
4
5
6
7
8
2.3.1 :007 > who_name_is
=> Jimmy
2.3.1 :010 > :who_name_is.object_id
=> 3572508
2.3.1 :014 > who_name_is = "Jimmy Tsai"
=> Jimmy Tsai
2.3.1 :024 > :who_name_is.object_id
=> 3572508

上述可以發現

宣告變數時, Ruby 會偷偷在底層建立專屬的 id
不管你重新定義幾次,同一個 Symbol(:who_name_is) 的 id 都一樣

你會想問,可以替既定的 Symbol 改名嗎?

你會得到一個 NoMethodError

$irb
1
2
3
4
5
6
7
2.3.1 :025 > :who_name_is[0] = "k"
NoMethodError: undefined method `[]=' for :who_name_is:Symbol
Did you mean? []
from (irb):25
from /Users/jimmy/.rvm/rubies/ruby-2.3.1/bin/irb:11:in `<main>'
2.3.1 :026 > :who_name_is[0]
=> "w"

你會想問,Symbol 可以拿來宣告嗎?

你會得到一個 SyntaxError

$irb
1
2
3
2.3.1 :021 > :who_name_is = "jimmy Tsai"
SyntaxError: (irb):21: syntax error, unexpected '=', expecting end-of-input
:who_name_is = "jimmy Tsai"

什麼是 String?

$irb
1
2
2.3.1 :027 > "who_name_is"[0] = "k"
=> "k"

可以看到 string 就可以成功替換
String 和 Symbol 都擁有 length、upcase、downcase 的方法!

再次拿 id 來驗證

$irb
1
2
3
4
5
6
7
8
9
10
11
12
2.3.1 :001 > st = "jimmy"
=> "jimmy"
2.3.1 :002 > st.object_id
=> 70136566672520
2.3.1 :003 > :st.object_id
=> 3572508
2.3.1 :004 > st = "jimmy"
=> "jimmy"
2.3.1 :005 > st.object_id
=> 70136566640600
2.3.1 :006 > :st.object_id
=> 3572508

上述結論:
Symbol obj_id 都一樣!
String obj_id 都不一樣!

總結,也是面試最愛問,Symbol 與 String defferent?

Symbol本身是【不可改變的字串】
創造 Symbol 時,記憶體【只會有一個 object_id

延伸閱讀:

otiann - Ruby女孩(13):到底字串跟符號什麼時候使用比較好?

Ref :

ihower大 - Ruby on Rails 實戰聖經
lazybios - Ruby:Symbol 与 String
高見龍 - Ruby 語法放大鏡之「有的變數變前面有一個冒號(例如 :name),是什麼意思?」

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×