2016年1月27日

[筆記] JavaScript中物件(object)和JSON格式的轉換

圖片來源:JavaScript 101

在上一篇文章中([筆記] JavaScript中的物件建立(Object) - Part 2),說明了如何使用object literal syntax來建立物件(也就是使用{ }來建立物件),這裡來談談JSON和object literal syntax的關係。

什麼是JSON


在網頁資料處理的過程中,我們常常將資料從一端傳到另一端(例如,從伺服器端傳到客戶端),這時候我們就需要一些共通的格式來方便包裝資料和解讀資料。

假設我們現在要傳遞一個物件的資料,這個物件長這樣:


XML

過去相當常用的一種資料格式是XML(EXtensible Markup Language)格式,它的型式大概會長的像這樣子:


在XML格式中,會用一個又一個角括弧把屬性名稱包起來,中間放值,最後再放封閉的角括弧(詳細的XML格式說明可參考:W3Schools XML Tutorial)。

JSON

然而XML格式雖然可以傳遞資料,但這麼做似乎顯得不夠簡便,因為光是屬性名稱就必須要打兩次,當我們的資料量很大的時候,可能會使得檔案變得很大,影響到傳遞的時間,因此後來就有人發現,我們何不使用類似JavaScript中object literal syntax的方式來傳遞資料呢?

於是就出現了JSON

JSON的全名是JavaScript Object Notation,之所以取做這個名稱,只要是因為它是從JavaScript中建立物件用的Object literal syntax演變而來(關於更詳細的JSON說明可參考:W3Schools JSON Tutorial)。

但是JSON 和 JavaScript的Object literal syntax還是有不同的地方,這點是非常需要留意的。

讓我們先來把我的上面的物件轉成JSON格式來看看:


JSON格式和JavaScript中使用{ }建立物件的樣子真的非常相似,幾乎就是把var xxx = { }這個{ }這個複製下來而已!但要特別注意的地方是:

  1. JSON就是一組字串。
  2. 在使用{ }建立物件時,屬性名稱是可以有引號也可以沒有的,但在JSON格式中,該屬性名稱一定要有引號。
  3. 若物件中的值為function,是無法透過JSON傳遞的。

將物件轉成JSON格式


在JavaScript中,要將物件改為JSON格式非常容易,只要使用內建的函式JSON.stringify()就可以了,例如我原本的物件名稱是person,我只需要輸入如下的指令,就可以將物件轉成JSON格式了。


轉換出來的JSON字串:


將JSON格式轉成物件



在JavaScript中,要將JSON格式轉回物件也非常簡單,同樣是透過內建的函式JSON.parse()


它就再次被轉換回物件了:


→回到此系列文章目錄

資料來源

[筆記] JavaScript中的物件做為namespace的簡單運用

圖片來源:JavaScript 101

在前兩篇文章中我們說明了在JavaScript中如何建立物件([筆記] JavaScript中的物件建立(Object) - Part 1[筆記] JavaScript中的物件建立(Object) - Part 2),在這篇文章中,我們則是會簡單說明如何運用物件。

我們先來看這段程式碼,複習一下:


想想看,如果我執行這段程式的話,呼叫出來的結果會是「你好」還是「Hello」?為什麼呢?



答案是Hello。



為什麼呢?因為JavaScript在解析程式的時候,會先建立好定義的變項名稱(即,greet),並把它存在記憶體中,這時候greet的變項已經被建立,而值則是"undefined",接著JavaScript才會去逐行執行程式,greet的值就從undefined-->你好-->Hello,有了如下的變化,因此最後呼叫出來的結果會是Hello(參考:[筆記] 談談Javascript 中的 Hoisting)。

使用物件來達到namespace的效果


Namespace簡單來說是指一個包含了許多變項和函式的空間。

如同上述的例子,因為這兩個變項一樣都叫做greet,可是一個是中文,一個是英文,因為變項名稱一樣的關係,它並沒有辦法區分哪個給中文用的,哪個是給英文用的。在其它的程式語言中,有些可以透過namespace(名稱空間)來達到這樣的效果,可是在JavaScript中,並沒有Namespace這樣的功能,然而,我們可以透過物件的概念來達到類似namespace的效果(faking namespace)。

實際的做法上,我們可以寫出如下的程式碼:


我們把分別建立Chinese和English這兩個物件,然後在裡面我們可以套用一樣的變項名稱greet,在呼叫的時候,只需要選擇你是針對哪一個物件裡面的greet去做呼叫就可以了!

這樣做有一個很重要的好處,就是當我們很多人在編輯一份文件時,假設A同事建立了一個函式名稱叫SayHI,很不幸的,B同事也建立了一個名稱相同的函式或變項,這時候就麻煩了,因為後面的會把前面的給覆蓋掉,這時候如果我們能妥善利用JavaScript中物件來做為namespace的使用,就可以避免變項名稱重覆所造成的問題

其他應用物件時可能碰到的問題


這裡我們可能突然想到Hello只是英文裡面打招呼的一種方式,所以我們想要把greet放在greetings裡面,像是這樣子:



這樣做是很直覺的方式,但是結果會發生錯誤:



上面的訊息顯示"Cannot set property 'greet' of undefined",意思是說,我們想要設置一個屬性是greet,可是這個屬性要設置的地方目前還是"undefined"。

之所以會這樣,是因為我們還沒告訴JavaScript,english當中greetings這個屬性的值是什麼,所以greetings建立後,預設的值是undefined,也就是像這樣:


這也就是為什麼我們沒辦法建立"greet"這個屬性(property),因為english.greetings並不是一個物件!

為了要能夠順利執行程式,我們要先宣告english.greetings是一個物件,這樣它才可以建立「名稱─值」配對在裡面,也就是我們才能再進一步給它屬性。


這時候程式就能順利執行。

或者我們也可以利用object literal syntax的方式,像是這樣:


這樣子的話,程式一樣可以順利執行。
→回到此系列文章目錄

資料來源

2016年1月26日

[筆記] 談談JavaScript中的物件建立(Object) - Part 2 | 利用大括號{}建立物件

圖片來源:JavaScript 101

在上一篇文章中我們提到([筆記] JavaScript中的物件建立(Object) - Part 1),我們可以先使用"[ ]"和" . "來建立物件,在這篇文章中我們則會使用object literal syntax的方法,也就是使用"{ }"來快速又簡便的建立物件。

使用{ }建立物件

在上一篇文章的最後,我們主要是使用new Object()搭配上"."的方式來建立物件。


呼叫出來的結果長這樣:



但其實在建立物件上有更快的做法,我們可以直接使用{ },我們可以把上面的程式碼,改成這樣:


透過這種方式,可以得到一模一樣的結果。

STEP 1

首先,利用{ }建立物件:


STEP 2

接著,就可以依序輸入「名稱-值」的配對進去:


STEP 3

在物件中建立物件的方法也一樣,在{ }裡面再放入{ }就可以了!


同樣地,如果不想在person這個物件裡面,再多一層的{ },也可以透過這種寫法:


看自己習慣用怎樣的方法,還要怎麼樣建立物件在閱讀上比較容易理解。

搭配函式使用物件



在我們建立好物件後,我們可以搭配函式(function)來使用物件,例如,我先把剛剛建立的物件person,改成叫做PJCHENder。


接著建立一個名稱為SayHI的函式,並且帶入我們的物件:


這時候,該函式就可以直接呼叫出物件裡面屬性的值:


直接在函式參數的地方建立物件



我們也可以直接在呼叫函式的同時建立物件,像是這樣子:


一開始看到這樣的寫法可能會覺得很奇怪,但其實這種方式和我們直接在函式的參數裡面輸入字串或數值是一樣的意思,只是這裡是建立一個物件。我們把這種直接在函式的參數中建立物件的方法稱做"creating object on the fly"。

一樣可以順利的回傳結果:



→回到此系列文章目錄

其他說明

不論你使用的是new Object、" . "、或者直接用"{ }"來建立物件,其實在JavaScript轉譯之後,本質上做的都是同樣的事。它都會將這個物件建立在記憶體中,並建立該物件的屬性(property)和方法(method)在記憶體中。

資料來源

2016年1月25日

[筆記] 物件是什麼?method 是什麼?談談 JavaScript 中的物件建立(Object) - Part 1

img
在這篇文章中我們將會說明如何建立 JavaScript 裡的物件(Object)

物件(Object)是什麼?

首先,我們要知道物件是什麼。**物件(Object)**簡單來說,就是一堆「名稱 - 值」的配對(key - value pairs)。至於可以放入哪些值呢?
第一種是原生的值(primitive),像是布林值(Boolean)、數值(Number)或是字串(String),而在物件當中,我們把這類的值稱做屬性(Property)。
第二種可以放入的值是物件(Object),也就是在一個物件裡面再嵌入一個物件,這種以物件為值的情況我們也把它稱作屬性(Property)。
第三種放入的值可以是函數(function),在物件的情況下,我們會把這種函式稱做方法(method)。 在物件中的每一個 Property 或是 Method 都會占據電腦當中一個記憶體的位置,在需要使用到的時候,把它們呼叫出來。

方法一:使用 bracket notation [ ]

建立物件

建立物件的第一個方法是使用 [ ][ ] 在 JavaScript 中被稱做 Computed Member Access
讓我們看一下例子:
這是利用 [ ] 建立物件的方法,首先我們建立一個物件,名為 person,接著開始給它「名稱 - 值」配對,例如,firstName 是屬性的名稱,PJ 則是它的值;lastName 也是屬性名稱,CHENder 則是它的值。透過這種方法,我們就可以建立物件裡面的各種「名稱 - 值」配對。

呼叫物件

我們也同樣可以利用 [ ] 來呼叫已經建立好的物件,[ ] 裡面如果放的是字串而不是變數,要記得加上引號 ' 像是這樣:
另外,如果是透過 [ ] 來呼叫物件的話,還有一個特別的地方,就是 [ ] 內可以放變數,像是這樣(當 [ ] 裡面放的是變數時不用加引號"),一樣可以讀取到物件的值,這個是用種方法二(.)做不到的:

方法二:使用 dot notation .

建立物件

第二種建立物件的方法是使用英文的句點 .,在 JavaScript 中被稱做 Member Access,建立的方法如下:我們在剛剛建立的 person 這個物件裡面,在建立一個物件屬性,名稱為 address。其實,我覺得可以把 . 翻譯成中文的「的」,所以這裡的意思就是,在 person 的裡面建立一個名稱為 address 的物件;在personaddresscountry,建立一個值為 "Taiwan",以此類推...。

呼叫物件

同樣的方法也可以用來呼叫出該物件的值:
當然,.[ ] 是可以交替使用的。

其他說明

在這段課程中,Anthony Alicea 提到使用 new Object 不是建立物件最好的方式,這點會在之後的課程再作說明。另外,雖然使用 [ ]. 都可以拿來建立物件和讀取物件,但他還是建議盡量使用 . 做為建立物件和呼叫物件的方法,這樣比較乾淨簡潔,在 debug 的時候也比較容易。

程式碼

// 建立物件
var person = new Object();
person["firstName"] = "PJ";
person["lastName"] = "CHENder";

// 呼叫物件

var whatIWant = "lastName"
console.log(person[whatIWant]); // CHENder

// 建立物件
person.address   = new Object();
person.address.country = "Taiwan";
person.address.city  = "Taipei";
person.address.locate = "101";

// 呼叫物件
console.log(person.address);
console.log(person.address.country);
console.log(person["address"]["locate"]);

參考

2016年1月20日

[筆記] JavaScript中coercion的實際使用--建立函式預設值(default value)

圖片來源:JavaScript 101

由於在目前的JavaScript中,撰寫函式的時候並不像PHP或其他程式語言可以直接賦予預設值(未來應該可以), 因此在這篇文章中,我們會說明如何用coercion這樣的特性來建立非常簡潔的函式預設值。

我們先建立一個函式,取名叫做greet。這個函式非常簡單,包含一個變數,就是去呼叫名字(name)而已。


在最下面的地方,我們去呼叫這個函式,並且代入"PJCHENder",可想而知的,console的結果如下:


如果在函式中沒有代入任何的值的話,會怎麼樣呢?



如果我們在函式中沒有將name給值,那麼會發生什麼事呢?


結果如下:


#1:和其他程式語言不太一樣的地方,JavaScript並沒有回傳任何錯誤的訊息,而是將name直接回傳"undefined"。這是因為在程式執行的過程中,一個新的execution context被建立,而name這個變項就被建立在函式裡面,只是還沒被給值而已,在變項建立後尚位給值前,該變項就被賦予了undefined這個值(這是類似Hoisting的概念,可參考:[筆記] 談談Javascript 中的 Hoisting)。

#2:undefined被強制轉換成字串

利用coercion這樣的特性建立預設值 (default value)

那麼,我們要如何利用coercion這樣的特性來建立預設值呢?

作法如下,我們新增一列指令就可以達到預設值的效果了。


這時候如果name沒有值,就會顯示<Enter your name here>。

為什麼這樣短短一行就可以當作預設值呢?

[筆記] 談談JavaScript的Precedence和Associativity中我們說明過Precedence和Associativity的觀念,所以當一列程式碼中,同時出現兩個運算子(Operators)時,我們可以在MDN Operator precedence來查一下"="和"||"誰的Precedence比較前面:


因為 "||" 比 "=" 擁有更高的precedence,所以會先執行"||"的部分,而且"||"是由左至右讀取。

所以讓我們先來看一下" || ":

我們可以發現,當我分別輸入true || false, true || 'Hello' 和 false || 'Hello'都會分別回傳不同的結果。

當左邊是true的時候,因為會先讀取到true,所以會直接回傳true;但當左邊是false的時候,就會判斷右邊是true會false,當右邊是一個字串時,它會判斷是true,同時回傳字串


同樣地,因為coercion的關係,如果"||"的左邊沒有值,則都會被判斷成false。



而這也就是為什麼我們可以用那一行簡短的指令,當作預設值的寫法,因為,當name不存在時就會是false,這時候就會讀取"||"右邊的字串,同時回傳該字串的值。

但這樣預設值的寫法有一個限制,就是變數不能是0,如果變數是0的話,會被當成false,結果則會跑出預設值

→回到此系列文章目錄

資料來源

2016年1月19日

[筆記] JavaScript中coercion的實際使用--if判斷式

圖片來源:JavaScript 101

在上一篇文章中([筆記] 談談JavaScript的coercion),我們談到了JavaScript中強制轉換資料型態(coercion)的特性。那麼實際操作上,coercion能夠帶給我們什麼樣好的處呢?

我們同樣先來看一段程式碼,我們用Boolean()將"undefined", "null", 和''強制轉換成Boolean型態的資料,看看結果為何?


結果顯示,不論是undefined, null或"", 最後都會回傳"false"的結果。


而我們就可以利用這樣的特性來撰寫if指令,如果a存在的話就執行...,如果a沒有值則...。


透過這種方法,我們就可以判斷a是否有被給值。但這種方法要特別留意的地方是 0 也會被強制轉換成false ,所以如果你的a有可能被給0這個值得話,這樣的方法就不太適合。

另外,如果在debug的過程中,發現a明明就有被給值,但if卻一直判斷是false的情況,也要特別留意是不是a的值其實是0。

→回到此系列文章目錄

資料來源

2016年1月6日

[筆記] 談談JavaScript的coercion

圖片來源:JavaScript 101

這篇來談談JavaScript中coercion的概念,coercion指的是將資料從一種型態轉換成另一種型態,在某些情況下JavaScript會根據它自己的判斷將資料轉換成另一種型式。

讓我們來看看下面這個例子:


其中1是數字,2則是字串,那麼a到底會得到什麼樣的結果?

答案是..."12"



為什麼呢?

因為JavaScript在執行這段程式的過程中,它會儘可能去的猜測你要表達的意思是什麼?在這裡它其實是把"1"當成了字串去處理,也就是將原本的數值轉換成字串的型式(coercion),所以才會變成12,因為1是字串、2也是字串,然後中間用字串連接子"+"連接起來,最後便成了12,而這個12其實也是個字串。

我們可以用typeof()這個指令來檢驗a這個變數的型態,會發現,的確回傳了a為字串的結果。


這個範例可以給我們什麼啟示呢?

有些時候我們在寫程式的時候,會像下面這樣,中間已經隔了一些程式碼,最後才來進行運算,也許你原本預期是得到"3"的結果,結果竟然回傳了"12",這時候,我們可以想到有可能是JavaScript中的coercion導致的。



→回到此系列文章目錄

資料來源