「直播」xdite教你克服情緒 & Nic 教你克服 DB

今天是一次兩個講師直撥,那背景音樂我聽出來是let it go很好聽。

xdite教你克服情緒

首先老師先介紹了一本書『腦能量整理術』是一位日本的腦神經權威著作,老師的網站上也有自己整理的筆記,這本書主要在講如何用科學方式控制情緒起伏,讓自己保持正面樂觀提高記憶力。

首先我們最常遇到『學習上』最崩潰的問題就是為什麼學習時間差不多的人做出來的東西會比我牛逼這麼多?

先來想想有沒有辦法讓自己沒有情緒,答案是不可能的,所以再來探討為什麼我們會有這個崩潰感?

大部分的原因是因為自己的大腦跑太快了開始爆衝了,腦袋想了一堆事情卻沒有辦法去實現,這時候焦慮感會直線的上升。

那以科學的角度來看是因為血液裡的血清素降低,血清素在晚上也會比較低所以人在晚上才會多愁善感,這時候要讓自己的大腦慢下來才能降低焦慮感拉回血清素,所以常常會聽人家說去走走路跑跑步去散散心,因為我們在做這種運動的時候大腦是需要專心的,專心才可以把四處暴衝的大腦給停下來。

那如何在寫代碼的時候讓自己的大腦慢下來?我們有時候不會隨時站起來運動,這時候還是要利用其他身體元件部分去執行,既然我們不能用腳站起來運動就用手去『寫』下來,記住一定要寫而不是用電腦打字,當專心做這件事情的時候大腦就會慢下來了。

老師給的建議

先拿出一張紙。

  • 『寫』下自己的最終目標
  • 把這個目標轉變成有實際數字的數據目標

首先第一個『寫』下自己的最終目標不難解釋,就是像上面講的讓自己大腦慢下來

那把目標轉變成有實際數字的數據目標是什麼意思呢?

像這次的魔改大賽,寫下的目標可能是我要拿到前三名,但是這個目標很籠統又模糊,因為自己的大腦開始想我要css寫得很漂亮,我要js做哪幾個很不錯的功能,然後好了,看了一下別人的牛逼網站崩潰感直接衝進來,大腦又開始爆衝了。

所以停一下,想一下怎麼拿到前三名,最重要的是拿到『票數』,但票數跟程式碼是沒有直接關係的,那怎麼拿到更多票數呢?

思考一下VIP會員一張是10票,非VIP會員一張只等於1票,所以當然我們要主攻VIP會員,那也許我們不是真正做一個很屌的網站去吸引他們(別用自己的短處打別人長處),而是上社群網站分享一些技術文或心得去跟他們做交換。

再不行取得VIP的票,我們也可以放在自己的公眾號去拉票,怎麼樣都是往自己最清楚的小任務去前進達,成任務,而不是望著自己模糊的大目標讓自己的大腦高速空轉。

再來以自己網站為出發點的話,不要一直想著要坐著比別人牛逼的功能,因為自己實力不到就是不可能做出來的,再者其實功能牛逼並不一定可以讓別人喜歡,最重要的是看重使用者的體驗和操作。

什麼意思呢?

體驗上或許你可以針對整個網站的style和配色做調整,讓別人一進入這個網站就感覺到很舒服,也都可以快速清楚知道怎麼要使用這個網站。

操作上自己做的功能可不可以真的解決掉使用者的問題,譬如說做了一個查詢系統,但是資料庫裡面只有十筆資料給使用者查詢,這時候這個功能做得再漂亮或在牛逼都只是沒什麼用的東西而已。

這就是把模糊的大目標(想進入前三名),切成許多細小又清楚的小任務,我們一直不斷的做前進這個動作,不要一直讓自己的大腦處在高速空轉的暴衝狀態。

Nic 教你克服 DB

在rails101裡面我們很常下db migration這個指令,那到底這個指令是什麼東西呢?

其實就是在操作資料庫裡面的資料

第一如果我們不這樣去下達指令,而是直接去資料庫裡面篡改資料,一筆兩筆或許真的沒什麼,但如果今天有一千筆資料我們會改到崩潰,加上這樣的錯誤率會大幅提升,最後搞得非常麻煩。

第二我們這樣子下指令都會有紀錄,是誰新增了什麼,大幅提升專案的穩定性。

第三我們可以做到遠端許多裝置去協作一個專案,像是db:migrate就可以把自己本地端的專案同步為雲端最新的狀態。

常用指令:
1.rake
db:drop
db:create
db:migrate
db:reset
db:seed
db:migrate
db:rollback

rake是什麼??
我們可以直接收尋 rails rake 是什麼,老師說Google的能力是很重要的。

Schema綱要

1.改了沒有用(改他也沒意義)
2.記錄DB的版本號(像是DB的Git)
3.目前欄位狀況(像是log一樣可以列出來)

老師推薦一個gem是annotate,他可以直接在model裡面註解schema的東西。

我們直接在專案底下下rake db:migrate:status可以看到目前數據庫的進度和狀態。
up是執行到這一步down是還沒執行或者是退後過

譬如老師先新增了一個資料庫(model) 名稱是post title:string,此時執行rake db:migrate:status會出現down是因為數據庫並還沒有新增(更新),此時可以開atom去看自己的db文件看變化,我們下rake db:migrate後他會新增東西,然後再下rake db:migrate:status剛剛的down就變成up了,這時候如果又下rake db:rollback文件會有東西被刪除(最後一次新增的),而下rake db:migrate:status又會看到剛剛的up變為down了。

migrate可以操作資料庫,而schema是可以把資料庫git化,查看版本大綱,那我們不用去動schema,因為他是自動在記錄的,所以rake db:migrate:status才看得到變化。

剛剛講的annotate套件是什麼?
在Github上直接查詢他就有許多資訊。

先安裝後bundle install,最好是下只幫model生成的指令(他的Github上面有),這樣資料庫會直接生成註解,我們不用一直出來看schema的大綱。

觀念

讓數據庫保持在前進的狀態
除非不得已才退一步

退一步之後修改完馬上進一步,盡量不要退太多,如果是很久以前的錯誤不如前進一步去修改錯誤(修補的概念),例如到第十步的時候第二步有錯可以去使用rename功能,那如何使用老師叫我們上網查就有很多了!

關鍵字示範:rails migration rename

Q&A:

1.如何實現管理員權限,分高低級?
google can can can有套件

2.聽不懂

3.如何複製別人網站的JS效果?
JS不太能直接抄,很難debug,還要考慮到他們用什麼套件,再來不要求好先了解簡單的就好,現階段多使用小套件就好。

4.有沒有推薦css或html的教程?不然很容易遇到挫折
收尋 w3c html就很多了。

5.heroku更新數據會有問題?
heroku不給執行drop,要去找一下在上面的執行方法。

6.如何不同的電腦做同一個專案?
下載dropbox或者是雲端的東西直接把整包專案的資料夾丟進去。

[JavaScript] by value V.S by reference的行為

在JS的其中一個重要觀念是當創造一個變數var a;他會佔據一個記憶體位置,而當賦予給他值的時候a = 1;會把a的記憶體位置拷貝並且指向這個純質(1)

這觀念或許很抽象,白話來講創造變數的時候他會是一個空白的記憶體,當你賦予它值var a = 1;的時候他會去拷貝1這個純質。

那什麼是by value和by reference呢?我們先來看最簡單的by value。

by value

只要給變數純質(primitive),例如數值、字串、布林值等非物件的東西會產生by value這個動作。

我們直接看看例子:

var a = 1;
var b = a;
a = 2;
console.log(a);  //print 2

console.log(b);  //print 1 

答案非常的直覺,但底下發生了什麼事情?

首先我們的程式碼會先產生Hoisting(創造與提升)這個動作,讓ab各自有一個記憶體空間,賦予a等於純質1,記憶體拷貝並指向了這個純質。

再來b = a;的時候因為a的記憶體剛剛拷貝和指向了一個純質,所以b的記憶體也拷貝並指向了相同的純質,這時候!!雖然ab的記憶體指向完全一模一樣的純質,但由於by value的行為其實a和b的記憶體位置是不一樣的!!!

白話譬喻的話就是a買了一棟信義區的房子,此時b說要買跟a一樣的房子,所以他們都有一模一樣在信義區的房子,但是地址是不一樣的,這就是by value的行為,非常好懂,再來我們看看by reference。

by reference

只要給物件(function算是物件)的東西會產生by reference這個動作。

再來直接參考下面的例子:

var a = { greeting: 'Hi'};
var b = a;
a.greeting = 'Bye';
console.log(a);  //print Object { greeting: "Bye" }

console.log(b);  //print Object { greeting: "Bye" } 

直接看結果我們發現b竟然跟a直接同化了!!發生了什麼事情?

比照剛剛by value的行為即使讓b直接等於a取得一模一樣的純質,但是b記憶體位置是一個新的位置

相反的by reference的行為並不會給b一個新的記憶體位置,所以直接變動a或者是b物件裡面的東西它們都會一起受影響,因為他們就是住在同一個屋簷底下。

想同的規則即使是在function裡面的參數(parameter)也是一樣

直接看例子:

var a = { greeting: 'Hi'};
var b = a;
a.greeting = 'Bye';
console.log(a);  //print Object { greeting: "Bye" }

console.log(b);  //print Object { greeting: "Bye" }

function changeName (obj) {
  obj.greeting = 'morning';
}
changeName(b);
console.log(a);  //print Object { greeting: "morning" }

console.log(b);  //print Object { greeting: "morning" } 

傳入changeName的參數會改動參數裡greeting的值變為morning,由於by reference的行為a也被我同步了!

如果是用物件實體(object literal)的方式指定物件的值,那麼會是by value

直接看例子:

var a = { greeting: 'Hi'};
var b = a;
b = { greeting:'Bye' };
console.log(a);  
console.log(b);  //print Object { greeting: "Bye" }

function changeName (obj) {
  obj.greeting = 'morning';
}
changeName(b);
console.log(a);  //print Object { greeting: "morning" }

console.log(b);  //print Object { greeting: "morning" } 

傳入changeName的參數會改動參數裡greeting的值變為morning,由於by reference的行為a也被我同步了!

如果是用物件實體(object literal)的方式指定物件的值,那麼會是by value

直接看例子:

var a = { greeting: 'Hi'};
var b = a;
b = { greeting:'Bye' };
console.log(a);  //print Object { greeting: "Hi" }

console.log(b);  //print Object { greeting: "Bye" }

結果不會同步!!

因為b = { greeting:'Bye' };這行等同於b自己創造了一了新的物件,所以ba已經不是共用同一個記憶體位置了,簡單的說b已經不和a住在同一個屋簷下,b自己買了新房子了!

如果是用b.greeting = 'Bye';這種方法是更改物件裡面的內容,也就是還在同一個屋簷下但是做了裝潢,當然兩個同居的人就會享有一樣的效果,這就是by valueby reference的行為。

了解了這個在規劃的時候要盡量避免踩上這些地雷,所以在操縱變數的時候要注意一下這些觀念,不然這算是非常難degug的東西,尤其在angular的$scope運用會死得很慘XD。

「直播」與Boostrap做朋友-Nic老師

什麼是Boostrap?

快速開發,不用寫太多css和html
目前最火熱的套件之一
更詳細的介紹可以直接在網上收尋bootstrap component即可,有中文版,但是不能複製代碼所以不好使用。
版本建議使用bootstrap3,4還不穩定而2又太舊。

如何測試

Nic老師今天使用panels做介紹,建議直接先複製官方網站的代碼到自己的程式碼上面看看效果是不是跟官方網站和自己想要的效果一樣,再把自己的程式碼帶進去。

而在一開始複製官方網站測試結果的時候希望不要被自己之前的code干擾,可以先把所有code進行註解,方法:
command + a先全選自己的程式碼 >>>> command + /可以進行全部註解 >>>> 找個地方把剛剛複製的程式碼貼上 >>>> command + s存擋 >>>> 到遊覽器commad + r刷新頁面看結果。

開發貼心小技巧:

  • command + x為剪下,這樣就不用複製代碼貼上後再回去刪除舊的代碼。
  • 在atom裡面只要打上div後按下tab會直接幫你做好一個div的tag。
示範的經過:

套上去之後上下左右沒有白邊,所以要自己改一下nav bar的css,讓他留下白邊,可是可能會造成另一個頁面有多餘的空白,可以使用margin-top: -20px;試試看效果如何,在調整上下的話負數的px是把區塊往上調,正數的px則為往下。

按鈕也有的元件可以套,收尋buttom或者是簡寫的btn都找得到,示範如下:
<% f.submit "Submit", class: 'btn btn-danger' %>

想要讓左右邊空白大一點或者是要呈現的區塊窄一點可以套上Bootstrap的格線系統col-lg-8並且自己做一個讓他置中的屬性,Nic老師做了一個centered的class並且給他margin: 0 auto;,要記得使用Bootstrap的格線系統一定要拿一個container去包住他:

index.html
<div class="container">
    <div class="row">
        <div class="col-lg-8 centered">
            something...
        </div>
    </div>
</div> 
style.css
.centered {
    margin: 0 auto;
}

開發貼心小技巧:

  • 做好一個區塊就刪除舊的,隨時看結果和更新程式碼,一步一步來才不會亂。

格線系統:

可以快速的做出自適應網頁

一開始Nic老師建議我們把這四大常用尺寸記下來:

  • XS超小螢幕-最常使用在手機
  • SM小螢幕-最常使用在平板
  • MD正常螢幕-最常使用在筆電
  • LG最大螢幕-最常使用在桌機那種正常螢幕

直接試試看如何使用:

index.html
<div class="container">
    <div class="row">
        <div class="col-xs-12 col-md-3 col-lg-8 borderBox">
            something...
        </div>
    </div>
</div> 
style.css
.borderBox {
    border: 1px solid;
    height: 50px;
}

直接對著遊覽器拉縮左右的寬度應該就會呈現效果。

格線系統一行分為12格,所以一行可以有2個6並排,或者3個4並排,或者2個3再加上1個6並排,以此類推最多一行有12格,高過則會被往下擠做換行動作,當然也可以像一開始的範例讓他一行只要用到8格再搭配置中。

開發貼心小技巧:

  • 打開chrom的開發者工具,拉縮遊覽器時右上角會顯示現在寬高有多少px。
  • 開發者工具可以直接對CSS做測試不會影響到原來的程式碼,調整好之後直接把東西複製到自己的code裡面,就不用一直做存擋刷新的動作了。

課程最後補充:
chrome的擴充套件Full Page Screenshot可以截網站全畫面,直接在收尋欄上照著打Full Page Screenshot就找得到。

Q&A:

這邊老師講很快我只憑印象和我的理解記錄下來,只能當作參考唷!

1.雖然不用背Boostrap和一些html的code,但有沒有更快速上手開發的方法?
多練習。

2.為什麼Boostrap有很多在CSS沒看過的代碼?
那是Boostrap框架自己的代碼。

3.不知道怎麼對應html和css,寫到後面很容易亂掉,有什麼辦法可以解決?
CSS的命名很重要。

4.很難實現自己網頁想要的style,不然就要花很多時間,尤其是收尋功能,怎麼辦?
收尋功能多上討論區看別人怎麼做,很多學長姐都有分享,在一開始想要做出自己想要的畫面花很多時間是很正常的事情。

5.寫code寫到很煩怎麼辦?
真的很煩就出去走走,讓自己散心一下吧。

6.git branch搞砸了怎麼辦?
分支要針對性大一點的開,不然一亂掉很麻煩,還有要開新的分支一定要回master開,不然從分支直接新開分之會是從那個分支再開分支出去,這樣很難管理。

7.排版是怎麼做的?
不明確的問題,建議熟悉Boostrap元件,多使用,甚至手畫出想做的網站再慢慢做出來。

8.放大縮小網頁怎麼做?
command + + = 放大
command + - = 縮小

9.分隔系統圖片會爆炸怎麼辦?
給圖片下一個class給他Boostrap的img-responsive屬性可以讓他有自適應。

10.想要Boostrap的動態功能有沒有辦法簡單做出來?
比較沒有,也比較不可能只針對一個功能做一個框架,比較小和特別的東西一定要自己做出來。

11.開發者模式怎麼讓他自己一個視窗?
在開發者模式的視窗有選項,可以點分離的圖示就會變成獨立視窗。

12.怎麼用兩台電腦同時開發一個專案?
可以使用google雲端dropbox之類的工具。

13.jumptron和box有什麼差別?
jumptron是Boostrap的套件,而box是老師自己寫的CSS

感謝Nic老師讓我們快速認識了Boostrap這個框架,果然線上閱讀文件的能力很重要嗄XD,今天老師也是帥帥der!

[JSON]什麼是JSON?為什麼要使用?

JSON是什麼?

今天剛好看到之前買的線上教學影片克服JS奇怪的部分介紹到JSON,所以說要真正認識JSON就一定要認識Javascript了!
尤其JSON又是真的受Javascript而啟發,他的全名也就是(JavaScript Object Notation)。

因JS的物件實體用法而生

物件實體(Object literal)是什麼呢?
稍微認識JS的人都知道要創造一個物件最基本的程式碼是:

var person = new Object();
person.name = "Kurt"; 
person.age = 18; 

JS的引擎有物件實體的功能可以用下面這種方法直接做到跟上面一模一樣的事情:

var person = {
    name: "Kurt",
    age: 18
} 

那這跟JSON有什麼關係呢?

以前傳送物件很浪費效率

以XML為例子,如果我們做資料傳輸直接傳送person這個物件電腦會幫我們傳類似下面這種東西:

<object>
    <name>Kurt</name>
    <age>18</age>
</object> 

但如果轉為JSON格式,電腦就只會傳送原本我們所打的JSON格式:

'{
    "name": "Kurt",
    "age": 18
}'

傳送過去再使用JS原生的function做簡單的處理(JSON.stringify)就變回於本的物件了。
比對一下傳送的字元幾乎少了一半以上!!所以JSON格式才會這個的熱門運用!

用這個例子第一次這麼的清楚知道JSON的由來,真有趣XD!

[CSS]我看到的浮動元素(float)與clear

在工作上遇到了要製作像Line一樣的聊天畫面,起先以為很簡單,但沒想到一路上學了超多東西XD,之前就一直很想知道clear: both;是幹嘛的,這次有了更深入的了解。

clear在MDN就可以查到他有很多屬性,這次就分享最常用的clear: both;就好(其實過程中我也只用到這個)。

浮動元素

什麼是浮動元素?網路上有很多專業解釋,但在這裡我用我觀察和測試的結果用白話解釋。

浮動元素就是把該元素抓起來漂浮在上面,聽起來很抽象吧?你可以想像一條橡皮筋綁著一疊紙錢,此時橡皮筋就像一個tag,一個容器(div, p, span...等等)之類的而他的大小被他裡面的紙錢(elements)撐大,而你紙錢從橡皮筋裡面抽出來的動作就像是給他float的特性,他在橡皮筋上面了,而橡皮筋因為裡面的紙錢被抽出來而失去了原來的大小。

但這畢竟不是照著物理世界行動的東西,所以他有下列一些特性:

1.擁有至右或至左的特性(因為float最常用的屬性是left和right而已)。
2.對容器不具實體(就像上述橡皮筋與紙錢的比喻)。
3.本身像內聯元素(inline element)一樣排列。
4.會與同層的內聯元素(inline element)連結。

這是我觀察的四個特性,一個一個解釋很簡單,但一次要面對兩個特性以上的話就會變得很危險,所以建議使用float的時候最好越單純越好,不要一次觸發他太多特性會很難維護,會很想把筆電折成兩半XD。

直接來看範例(或者點我看線上實作):

html
<div class="wrapper">
    <div class="box">stone</div>
    <div class="floater">ff ff ff ff ff </div>
    <div class="floater">ff ff ff ff ff </div>
    <div class="box">stone2</div>
</div>
css
.wrapper{
  border: 1px solid blue;
  padding: 10px;
  width: 200px
}
.floater {
  border: 1px solid;
  width: 20px;
  float: left;
}
.box {
  width: 100px;
  border: 1px solid red;
}

首先看充滿ff的黑色框框是我使用float: left;讓他產生第一點特性的至右。

再來可以看到他對他的容器有藍色框框的wrapper並沒有實質的佔體積,所以黑色框框是直接超出藍色框框的並沒有把它撐大。

第三是他像內聯元素一樣排排站好,就像這種tag一樣,可以看到兩個黑色框框是站在一起的。

最後一點很有趣,他會跟別人的內聯元素結合!你可以看到如果第二個紅色框框的stone2還有空間讓兩個黑色框框置入,他會挪出空間,並且右讓黑色框框符合他第一點的特性讓他至左。

再來如果剛剛第二個紅色框框的stone2並沒有空間讓他置入呢?
他會迫使stone2的內聯元素換行所以會撐大stone2的紅色框框。
稍微改一下CSS裡的box屬性修改就會有下面效果:

css
.box {
  width: 60px;
  border: 1px solid red;
}

stone2被撐大了!
那如果我強制設定紅色框框的高度不讓他被撐大呢?

css
.box {
  width: 60px;
  height: 40px;
  border: 1px solid red;
}

天阿,雖然紅色框框的區塊元素(block element)排列特性是正確的,但裡面的內聯元素卻被搞到離家出走了!!

如果還有人可以這樣子維護和開發的下去我真的會很欽佩他,如果是我到這裡就會想要砍掉重練了XD,所以說在使用浮動元素的時候最好是用單純的使用越好,不要一次使用它太多特性。

clear

首先可以直接去觀察MDN提供的幾個範例玩玩看。

我觀察出的特性:

clear可以把一個元素左右邊的浮動元素清除掉,所謂的清除掉並不是刪除他,而是一個王不見王的感覺,不是你換行就是我要換行,反正不是在同一行就對了!

clear使用的情況很多,這邊只分享我遇到的問題,我想要做一個類似像賴聊天的泡泡框,當然做左邊的沒有問題,最大的問題是右邊的泡泡框。

所以我需要把裡面的一個區塊至右,並且因為區塊內的元素多寡大小而自動向左邊變寬或變長,最後外面的容器也要隨著裡面的區塊改變高度,所以統計一下我要做的事情:

1.容器(wrapper)隨著區塊的大小改變高度,這裡用padding: 10px;可以做到。
2.區塊可以隨著裡面元素的多寡大小自動變更寬或長,這裡用display: inline-block;可以做到。
3.我需要把區塊至右,而且區塊是向左邊變寬,這裡用float: right;可以做到。

那我們來開心寫code吧!

html
<div class="wrapper">
  <div class="block">
   text<br>
   I real want succeed
   </div>
</div>
css
.wrapper{
  width: 200px;
  border:1px solid black;
  padding:10px;
}
.block {
  border: 1px solid blue;
  display: inline-block;
  float: right;
}

發生什麼事情了!???
為什麼我的wrapper包不住它!?
我想想阿靠就只是因為float的第一個特性讓他撐不開容器而已,換個屬性也可以囉!於是...

display: absolute;會產生跟float一樣的漂浮特性。
失敗。

把泡泡框margin和padding到最右邊後但是泡泡框是往右邊長。
失敗。

做一個區塊元素去比照這個泡泡框的高度一起長高?我好像找不到這個方法...XD。
失敗中的失敗。

想來想去查來查去剛好看到了有人說clear這個方法可以撐開因為float而撐不開的容器!
只要在容器最後面加上一個擁有clear: both;的tag就行了!

於是乎...:

html
<div class="wrapper">
  <div class="block">
   text<br>
   I real want succeed
   </div>
   <div class="clear"></div>
</div>
css
.wrapper{
  width: 200px;
  border:1px solid black;
  padding:10px;
}
.block {
  border: 1px solid blue;
  display: inline-block;
  float: right;
}
.clear {
  clear: both;
}

終於做出我要的效果了...這是眼淚嗎??
終於可以告老返鄉了~耶~~!!

最後也推薦看看這個部落客寫的详解CSS float属性哦!

[JavaScript - Udemy] Hoisting(創造與提升)

之前在Udemy的平台上趁特價買了JavaScript全攻略:克服JS的奇怪部分的中文課程,似乎是直接翻譯JavaScript: Understanding the Weird Parts的英文課程,在英文課程裡使用者回饋的評價算是很不錯的。

Hoisting(創造與提升)

這個階段是Javascript在初始化的時候會執行的動作。
當Javascript在一行一行執行程式碼以前,會先空出記憶體把所有變數和函示創造出來,但是先沒有放值進去。

我們直接看看範例(console.log後有斜線註解的地方代表有執行成功並寫出結果):

var a = 'Hi!';
function b () {
    console.log('Is b!'); //"Is b!"

}
console.log(a); //"Hi!"

b();

到這邊不難理解Js從第一行執行到最後一行會發生什麼事情以及他的特性,那如果把程式碼換個位置呢?

console.log(a); //undefined

b();
var a = 'Hi!';
function b () {
    console.log('Is b!'); //"Is b!"

}

第一行的console.log(a)並不是print出"Hi!"而是undefined,這是因為Javascript在初始化只會先空出記憶體去創造變數和函示,直到執行到給予該變數(例如:var a = 'Hi!';)。

以我們人類的看得懂的程式碼角度來看,Javascript在Hoisting的階段做了下列事情:

var a;
function b () {
    console.log('Is b!');
}

但如果我們沒有先創造創造變數的話Javascript就會報錯囉!
例如改變剛剛的例子把var a = 'Hi!';這行拿掉:

console.log(a);
//錯誤:Uncaught ReferenceError: a is not defined

b();
function b () {
    console.log('Is b!');
}

執行環境

再來要順便淺談一下執行環境問題,Javascript的Hoisting是在該環境唷!譬如剛剛的程式碼是在全域環境,此時Hoisting在全域環境的有本來就有的windowthis之外有自己創的變數a函示b,如果創造的變數不是在全域環境而是在函示裡面呢?(順帶一提現在開始是我個人推測、測試與驗證XD)

console.log(a); //undefined

b();
console.log(c);
//錯誤:Uncaught ReferenceError: a is not defined

var a = 'Hi!';
function b () {
    var c = 'Yo!';
    console.log('Is b!'); //"Is b!"

}

此時在執行console.log(c);時又報錯了因為全域與函示是不同的環境,所以在Hoisting的時候找不到變數c可以創造,所以程式碼再改寫一下:

b(); //"Is b!"

function b () {
    console.log(c); //undefined

    var c = 'Yo!';
    console.log(c); //"Yo!"

    console.log('Is b!'); //"Is b!"

}

我們發現函示裡面Hoisting運行的方式跟全域的方式是一樣的,那我們來做個執行順序的統整吧!

console.log(a); //undefined

b();
var a = 'Hi!';
console.log(a); //"Hi!"

function b () {
    var c = 'Yo!';
    console.log(c); //"Yo!"

    console.log('Is b!'); //"Is b!"

}

Hoisting沒問題之後再依造Javascript一行一行執行程式碼的特性,我們得出在console裡print出的順序為:undefined > "Yo!" > "Is b!" > "Hi!"

執行環境的地方是個人測試與淺見,如有觀念錯誤或更好的解釋方法歡迎留言糾正一下囉!

[JavaScript]map取代push取得Json裡的資料問題紀錄

map取代push實例

今天跟一起寫code的群組討論到JS世界裡盡量不要去使用直接改變變數的function,例如這邊的push,雖然我還不太懂切確的觀念是什麼不過還是分享一下朋友教的寫法,這種方法似乎比較精簡也直觀。

先紀錄我原本的寫法,在接取api的資料經常會碰到這種Json格式,我想要取得每個物件的name:

var apiArray = [
{
    name: 'Kurt',
    age: 25
},
{
    name: 'Andy',
    age: 40
},
{
    name: 'Maggie',
    age: 20
},
{
    name: 'Mary',
    age: 35
}]; 
var nameArray = [];
for (var key in apiArray) {
    nameArray.push(apiArray[key].name);
}
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

朋友教我使用map去擷取:

var apiArray = [
{
    name: 'Kurt',
    age: 25
},
{
    name: 'Andy',
    age: 40
},
{
    name: 'Maggie',
    age: 20
},
{
    name: 'Mary',
    age: 35
}]; 
var nameArray = apiArray.map(function(obj){
    return obj.name;
});
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

兩種方法在這種小地方或許看不出來,但就直觀維護上這種方法看到return obj.name就大略知道在做什麼事情了。

[JavaScript] split 分割字串

split(分割字串)

Syntax(語法):

str.split([separator[, limit]]);

參考文章:Mozilla Developer Network(MDN)

字串分割完會變成陣列

直接看範例:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ');
console.log(arrayAfterSplit); //["apple", "and", "banana", "are", "my", "favorite", "fruits."]

這時候要取得哪一個想要的字串只需要使用separator[index]就行囉!

當然我們可以分割再分割

var stringToSplit = "?id=12345678&passwd=00000000";
//在這裡我只要12345678這個字串時要做兩次分割

var arrayAfterSplit = stringToSplit.split('=');
console.log(arrayAfterSplit); //["?id", "12345678&passwd", "00000000"]

//這時候做第二次切割

var theIdNumber = arrayAfterSplit[1].split('&')[0];
console.log(theIdNumber); //"12345678"

選擇切出幾塊字串

使用方法:
split(separator, number);
直接看範例:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ', 3); //只取三塊

console.log(arrayAfterSplit); //["apple", "and", "banana"]

搭配.join()更換字元

在MDN的範例裡面我發現有趣的東西是搭配.join()可以做到更換字元的效果:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ').join('/');
console.log(arrayAfterSplit); //"apple/and/banana/are/my/favorite/fruits."

要注意這裡console.log出來的不是陣列又變回字串了!
join裡的東西會自動填入剛剛split的切割位置。

小記

會遇到這個問題是因為我遇到要利用網址(URL)取得使用者的id,這樣讓使用者在點進去網址的時候可以利用這個id得到他的資料,所以會搭配到var currentLocation = window.location;這個方法,例如網址為:
https://somecompany.com/somepage?id=123456
此時一進去這個連結我要用123456這個id去接取api初始化屬於該使用者的頁面資料:

var currentLocation = window.location;
console.log(currentLocation); //https://somecompany.com/somepage?id=123456

var arrayAfterSplit = stringToSplit.split('='); 
console.log(arrayAfterSplit[1]); //"123456"

這樣就可以取得id囉,當然window.location取得的狀況有很多種所以一開始一定要先console.log下來看一下。

HTML Email(電子郵件內網頁) 問題紀錄

麻煩的outlook電子郵件網頁

上一篇文章後續還是踩到了一些雷,再來紀錄一下。

line-height

上篇文章有提到這個屬性還被大多數瀏覽器和信箱支持,但在用程式開啟的outlook裡面它不是不支持,而是如果寫在<table>這個tag裡的話他不支持(囧)。

也就是說瀏覽器打開的話下面例子是ok的:

<table style="line-height:20px;">
    <tr>
        <td>element</td>
        <td>element</td>
    </tr>
</table>

但在程式打開的outlook不支持寫在<table>裡所以我們要改寫成:

<table>
    <tr>
        <td style="line-height:10px;">element</td>
        <td style="line-height:10px;">element</td>
    </tr>
</table>

可不可以寫在<tr>上我還沒測試過,因為每一次測試都是要從主管那更新所以我不好意思一直測試XD,再來在同一個<tr>的tag裡面是否只需要寫一個<\td>就好也不得知,總之照著個方式寫是ok的哦!

超連結<a>的文字顏色

如果想要改變點下超連結之後的顏色,也就是做到Visited的動作以前我們可以用選擇器來辦到:

.somelink:visited {
    color: #fff;
}

但是inline style卻沒有這種寫法,我們只能在tag裡面使用!important強制讓他一直維持一種顏色:

<a style="text-decoration:none; color: #fff !important;" href="#">element</a>

參考這篇Stack overflow

當然在遊覽器上看都沒問題,只不過問題又出在程式上開啟的outlook....,我用線上產生的html可行(國外有網站是可以線上排版後幫你產生html)但自己做的html卻失敗,於是我直接把按鈕做成一個圖片檔放上去了。

總之最後終於把html email告一段落了~

HTML Email(電子郵件內網頁)

HTML Email

這陣子第一次碰到要做一個可以當Email發送的HTML檔案,感覺有中文解說的網站不多(也許是我關鍵字下得不好),總之如果打HTML Email是可以找尋到國外不少資源,再來介紹我當中遇到的每個地雷。

完全使用inline style控制style

第一次遇到這個工作時我天真的以為不就跟平常瀏覽器用的HTML一樣把HTML和CSS做分離,設計師還出圖的很簡單應該一下做完了。

沒錯是一下就做完了,但是完全不能使用!!!

因為在每個個大郵件他們都有自己的CSS,所以會把你傳送檔案裡有CSS的屬性大多都會擋掉,所以要考慮各大瀏覽器的相容度之外,每個郵件的相容度是不一樣的(gmail, outlook打開的效果不一樣),所以要回歸最原始最基本的做法:

<div style="width: 100px;height: 100px;border: 1px solid black;"></div>

以上就是inline style的寫法,記得完全避諱使用class,雖然網路上有些人似乎有成功使用選擇器去input(就是寫class的做法),但我自己試過幾個是失敗的。

盡量完全使用table

為什麼要用table呢?因為在email中很多的CSS屬性是不相容的,像是position, float等竟然不能使用啊!變成說我們的切版只能實實在在地用table硬刻出來了,雖然我們的padding, margin在大部分的郵件還是有效的,但如果是要寄給outlook的郵件就不建議使用了!待會會解釋。

特殊的形狀一律使用圖片取代

什麼意思呢?
因為我們的border-radius, rotate等等也都不太能使用了,所以有什麼特殊的圖形盡量上傳到網路上用<img src="#">這個tag去實現吧!

重新認識基本的table屬性

雖然table可以稍微切版,形狀可以直接使用圖片,但平常我們要把東西調精準的話table一定不夠啊!一定要搭配margin和padding甚至position等等,為什麼不能使用呢?

剛剛提過position是完全不用考慮了,但如果要寄給outlook的話margin和padding也是不建議的哦!那怎麼辦?我們還有原始的table屬性可以使用!

  • cellpadding
  • cellspacing
  • border
  • line-height
  • align
  • valign
  • colspan 這幾個原生屬性要好好利用哦,可以把內文位置再加以調整的工具不多了啊! 所以說HTML Email的版面也不要太複雜了

大部分前四個屬性我都會直接灌在table上面了

<table style="width: 100%;font-size:14px;line-height:30px;" cellpadding="0" cellspacing="0" border="0">
</table>

再搭配chrome的開發者工具就很好先做初始調整了。

非瀏覽器開啟的outlook不吃<div>這個tag

非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
這個太哭夭了我要講三遍,如果有在用公司郵件的大多都會接觸到這個工具,就是outlook不一定在瀏覽器上開啟,他本身就有一個程式是打開郵件的,這個程式不吃<div>這個tag!!!
也就是說在<div>裡面加上的style會完全忽略!千萬要小心!

總結

所以如果要做大部份郵件、瀏覽器甚至是程式打開的outlook都正常的HTML Email,照著上面的步驟應該就不會出太大的問題摟!

至於有沒有更多的屬性可以用或更好的做法那肯定是有的,只是我就沒再多做研究下去囉!這是我第一次遇到的HTML Email功課,希望能幫大家能避開一些地雷。XD

還有續集~請點我看文章

3/22補充:感謝FB上Front-End Developers Taiwan社團有人分享的HTML Email適應表網站