2014年11月17日 星期一

20141117 今日學習

開始學習自定義的pseudo classes
對於這主題,估狗找到另外三篇相關文章

<第一種寫法>
首先我先閱讀Document.registerElement()這篇文章,如果我們想要用個客制化的element,就必須使用var container = document.registerElement(tagName, optional )。registerElement()的第一個parameter就是我們的custom Element的名字,第二個parameter是可有可無的,所以一般來說我們可以直接用var customTag = document.registerElement('tagName')即可在下一段會討論如何用第二個parameter,不過要注意,到這一步你只是建構出了一個名為customTag的constructor,若你要生成一個可以用的object,則需透過new customTag()。接著你就可以把customTag加入你的DOM,透過以前學過的
document.body.appendChild(new customTag())
。到了這一步,你已經為你的body tag裡面生成了customTag這個element,裡頭還是空的啊,所以我們依舊要在script下繼續撰寫,以這篇的diagram為例,用Tag的名字取得Tag,透過var mytag = document.getElementByTagName('customTag')抓到你自己做的的customTag這個tag後(藉由mytag這object),並為它加入些內容,例如mytag.textContent = "handsome",這篇文章結束。

接著學習Custom Elements: defining new elements in HTML這篇,直接從Registering new elements這節開始,在這篇就提醒了剛剛疏忽的重點,我們客制化的tag,它的命名一中間一定要有dash,即"-",於是我們會生成出像是<x-tag>、<my-tag>、<fresh-tag>...etc。所以應該改寫為var customTag=document.registerElement(custom-Tag),為了讓parser解析器區別原生與客製的element,所以要加dash。

這篇文章接著提到了registerElement()的第二個parameter,跳轉到同一篇的文章的Adding JS properties and methods這節registerElement()的第二個parameter是可以讓我們為custom tag加入properties and method。

(以下2014/11/18更新)
這節的paradigm,提供了我們一個不錯的架構與思考邏輯,來學習如何為我們的custom tag 加入一些properties and method。在paradigm中可看到,它是在registerElement()的第二個parameter寫下{prototype:XFooProto}。這個XFooProto是一個variable,透過Object.create()所定義的,OK  那Object.create()是什麼? 於是估狗到這篇文章Object.create() - JavaScript | MDN。原來Object.create()會產生specified prototype object and properties。Object.create()的synatx如下Object.create(proto [, propertiesObject])。可以看到parenthesis內的寫法很奇怪,但她其實是代表Object.create()裡有兩個parameters。第一個proto是指prototype object,參考自Using "Object.create" instead of "new" - Stack Overflow,裡面的回覆裡有一段說得很好,Object.create()的優勢是可以直接繼承其他object
  • This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.
接著讓我們先跳到Object.create() - JavaScript 第一個paradigm來實際體會吧。如paradigm所示,一開始先透過function keyword去創造一個名為Shape的constructor,並為Shape賦值x, y這兩個properties。但是我們的shape constructor裡沒有method,所以透過Shape.prototype.move=function{}來為我們的shape加入method。後來發現我對prototype的記憶有點模糊了,於是回去讀20141101 今日學習,並搜尋JavaScript Prototype in Plain Language | JavaScript is Sexy,回去讀自己的筆記,一開頭我就寫下property也是variable,換句話說,property是object,JavaScript Prototype in Plain Language這篇文章在Prototype Property: Prototype-based Inheritance這節有著下面的一段話
  • In JavaScript, you implement inheritance with the prototype property.
所以我們看到的Object.create(Shape.prototype)或var XFooProto = Object.create(HTMLElement.prototype),Object.create()裡面的第一個parameter都是object
注意,以Shape這constructor為例,你不能只寫Object.create(Shape),這樣的寫法是錯誤的,Shape是由function keyword所定義的,他是一個constructor不是一個variable。對於Object.create()的第一個parameter是object有更深的體會,我們閱讀Object.create(): the New Way to Create Objects in JavaScript這篇文章的The Object.create() Method這節,請閱讀這節的第二個paradigm,另外也可閱讀"Object.create" instead of "new" - Stack Overflow綠勾的paradigm,如此一來就一目瞭然了。

至於第二個parameter是作什麼用的呢?我們可以透過Object.create()來繼承其他的object,那如果我想要為我創造的這個object加入新的properties and methods呢,這時我們就要用第二個prarmeter了,請先回過頭來讀Object.create() - JavaScript 這篇的第三個paradigm

(以下2014/11/19更新)
先讓我們繼續閱讀"Object.create" instead of "new" - Stack Overflow綠勾的paradigm,它下面的文字就有說,Object.create()的第二個argument就是拿來為我們要新創的object設定properties,也可以透過另一種方式Object.defineProperties() and Object.defineProperty()

OK,何謂Object.defineProperties() and Object.defineProperty(),以及要如何用?參考閱讀How to Create Custom HTML Elements | Treehouse Blog,搜尋:Object.defineProperty(),可以看到Object.defineProperty()有三個parameters,第一個要是你的prototype object是你想要加入property的那個object,第二個是name of property,第三個是property的內容,在第三個parameter,你可以設定property的value與writeable。
  • The first parameter should be your prototype object; the second is the name of the property; and the third should be an object describing the behavior of that property. This is where you can set a default value as well as specify whether the property is writable or read-only.
(以下2014/11/20更新)
在閱讀JavaScript Getters and Setters這篇的The official way: Object.defineProperty這節,裡面的第二個paradigm之後的文字,有著對Object.defineProperty()較妥當的例子,Object.defineProperty(person, 'age', {value: 42});創造出person.age,而且將age的value設為42
(以上2014/11/20更新)

<第二種寫法>     <這邊有custom tag的完整邏輯> 
對於Object.create()有基本了解後,現在我們可以回到Custom Elements: defining new elements in HTML的Adding JS properties and methods這節,已經有能力閱讀這節的paradigm。透過Object.create()所產生的object,如果要加入method,用傳統的createdObject.method=function(){...}即可,這段paradigm為我們提供一個完整的架構,step.1 and 2我們自定義了var XFooProto的value,即XFooProto的method and popperty,但是這只是定義出來,在我們的DOM裡還沒有這個definition,於是Step.3,我們要為我們的DOM註冊這個定義,透過var XVoo=document.registerElement('x-foo', {prototype: XFooProto})。現在我們的DOM已經有了它的定義,下一步我們要創出instance aka 實體,透過xfoo=document.createElement('x-foo'),到此我們已經創出instance,現在我們要把這instance加入我們的DOM的body tag裡面,透過document.body.appendChild('x-foo')

圖片化上面思維的概念   (以下2014/11/25更新)

以上是第一種方法,為我們的DOM register new element(只下定義,尚未create instance),如果不想要寫那麼多步驟,也可以參考這節的第二個paradigm,直接寫
var XFoo=document.registerElement("tag-name",{
      prototype: Object.create(ProtoOnject, {values, use get and set})
    }
)

<第三種寫法>

 (以上2014/11/25更新)
個人較偏愛這樣子的寫法,你可以少寫一次var就盡量少寫,但是這樣的寫法要學習get/set,印象中在Object.create(): the New Way to Create Objects in JavaScript這篇文章的The Object.create() Method這節,在這節的第二個paradigm也有看到如此寫法,2nd paradigm後面的文字一學習發現就發現Descriptor這new term。Descriptor有Data DescriptorAccessor Descriptor這兩種。我們先來討論Accessor Descriptor,因為我們要用get and set ,這兩個東西其實很簡單,如其字面意義一樣,get是取得,i.e: obj.prop,你只是取得object的property,你不修改property內的value,get: function(){return something}。而set是設置,i.e: obj.prop="fresh value",你取得object的property後可以對其value做修改,
set:function(value){constructor's property=value.doSomeThing}。

(以下2014/11/20更新)
有約略的概念後我們繼續閱讀JavaScript Getters and Setters這篇文章,這篇一開頭就說傳統的JavaScript coding邏輯很醜 XDDDD,然後進入第一個paradigm,恩....很好,toString的用法是???於是我估狗找到JavaScript String toString() Method這篇,但僅是知道這樣還不夠,JavaScript Getters and Setters這篇的第一個paradigm裡還有一個split method,於是我又估狗JavaScript String split() Method這篇文章,這篇文章帶我們理解split method會透過",",把我們的string切割成數個substrings,然後return arrays。其用法如下,string.split(取代的內容)。

i.e: 若有一串string:var str = "How are you doing today?",接著你把它用分割,若你想要以"a"為界線分割string,並把結果全都放在一起,則可以寫var res=str.split("a"),則output:How ,re you doing tod,y?,若你想要分割空格(" "),則可以寫var res = str.split(" "),如此一來output:How,are,you,doing,today?。在剛剛我們看到把分割結果都放在同一個object裡,那我能不能把分割節果分開來呢,當然還是可以,我們再回來看JavaScript Getters and Setters這篇的第一個paradigm,先寫var words = name.toString().split(' '),
接著再寫this.firstName = words[0] || ' 'this.firstName = words[1] || ' '
如此一來不用宣告array,你就直接把words這object當作一個array。

再來讓我們注意一下,為何JavaScript String split() Method的paradigm只要寫var res = str.split(" ")JavaScript Getters and Setters的paradigm是寫var words = name.toString().split(' '),這其實是因為要確保input進來的東西(name)是string,所以先用toString method把它轉成string,再用split method把它分割。

OK,基礎知識的學習完成後,我們還是要回歸正題學習JavaScript Getters and Setters。約略閱讀這篇後發現,在這篇文章所看到的第一個get/set的寫法並不是正統的寫法,請從The official way: Object.defineProperty這節開始,會發現到跟我們以前看過相同的,關於get/set的寫法,get:function(){...}與set:function(value){...}。另外發現有了get and set這兩個keyword,則稱之為accessor,這讓我們想起曾在Object.create(): the New Way to Create Objects in JavaScript這篇文章的The Object.create() Method這節看過。回去閱讀先前的記錄get and set這些accessor是用在設定object的property時用的
(以下2014/11/25更新)
閱讀The official way: Object.defineProperty這節時,他有提到為何要用這寫法,最大的好處是我們不只可以使用get/set,還有configurableenumerable這兩個keys可以用。
  • configurable (false by default): if this is true, the property's configuration will be modifiable in future.
  • enumerable (false by default): if true, the property will appear when looping over the object (for (var key in obj)).

但其實accessor裡不只這些,我們回去讀Object.create(): the New Way to Create Objects in JavaScriptData Descriptors這節開始往下看,可以看到在處理object的property時,可以透過兩種descriptor還處理,分別是data descriptor與accesor descriptor。早先我們學的get/setaccesor descriptor,而writable、configurable、enumerable、value這些keys則是data descriptor

data descriptor的default皆為false若要啟動起改為true,(i.e  writable: true)。要注意,若是想要讓你object裡的properties能夠修改,一定要把data descriptor改為true,若沒改就算你有修改,但是output結果並不會改變,compiler也不會報錯。

data descriptor
  • writable:讓你可以修改property裡value的值,JavaScript Getters and SettersThe official way: Object.defineProperty這節的第三個paradigm非常清楚。
  • configurable:讓你可以新增或移除object裡的property,透過delete operator,請參考delete operator - JavaScript | MDN
  • enumerable:讓你可以使用for-in loop,for-in loop請看下面的討論。
  • value:就只是定義property的數值。

插曲:
來討論一下for-in loop,最早曾在20141101 今日學習這天學習過,但老實說觀念還不是很清楚,所以我們現在來學習for...in - JavaScript | MDN這篇文章。喔~~滿有趣的,for-in loop是專門設計給enumerable這descriptor用的,他是設計用來處理object裡的properties,透過跌代(interation)快速建立object不同的properties。寫法如下:for(propName in obj){...}。在這網頁的第一個paradigm可以清楚看到for-in loop的用途,首先先定義一個object,裡面有a,b,c三個properties,var obj ={a:1, b:2, c:3}
接著用for(prop in obj ){console.log("show the obj." + prop + "=" + obj[prop])}
如此一來就會output出
show the obj.a=1
show the obj.b=2
show the obj.c=3
for-in loop就是一個簡單地快速顯示出你的object裡有哪些properties,以及他們的value。

data descriptor的各種example可參考JavaScript: Property Attributes: Writable, Enumerable, Configurable這篇,所以現在來學習這篇

到此get/set以及各種data descriptor的學習告一段落,學習完畢

Custom Elements: defining new elements in HTMLAdding JS properties and methods這節
學習完畢,從Extending elements這節繼續。有趣了,透過registerElement,你可以繼承native elements或是custom elements。若你想繼承native elements,以button為例,在registerElement的第二個parameter可以用
{prototype: Object.create(HTMLButtonElement.prototype), extends:'button'}
custom element繼承native element,則稱之為type extension custom elements

學習完inherit native elements後,接著學習繼承 custom elements,Extending a custom element這節開始。結果內容超短 XD,一樣寫extends:' custom-element '。(PS: 別忘了custom element的命名中間都要dash)

(以下2014/11/27更新)
How elements are upgraded這節開始。   從這裡開始

 

                                           

(以上2014/11/18、11/19、11/20、11/25、11/27更新)

沒有留言:

張貼留言