0%

完成後的成品

觀察須製作的功能

  1. 重新整理網頁後,保有過去執行的狀態:localstorage
    • 實作內有使用:
    • localstorage:setItem,getItem
    • jason.stringfy/jason.parse

  1. 在new transation輸入資料後,會將資料傳入history中
    • add transation之後,頁面不會刷新(spa)(e.preventdefault)
  2. 摸到history中的項目,會出現刪除符號,點擊後刪除

  1. 輸入的金額,會顯示於上方income、expense,並且計算總額
    • 有正負值
    • 計算收入、花費

呈現完整語法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
$(document).ready(function () {
//預設值的設置,取得存在本地的資料或是空陣列
var transactions = JSON.parse(localStorage.getItem('Transactions')) || [];

//陣列初始
if (transactions.length > 0) {
initHistory(transactions);
}
//點擊按鈕的事件
$('.btn').click(function (e) {
e.preventDefault();
//console.log('click');
//取得表格中的值
const text_val = $('#text').val();
const amount_val = $('#amount').val();
let id = generateID();

addTransactions(id, text_val, amount_val, transactions);

//推入陣列
transactions.push({
id: id,
name: text_val,
amount: amount_val
})


localStorage.setItem('Transactions', JSON.stringify(transactions));


})
updateValue(transactions);

});


//在list中插入
function addTransactions(id, name, amount, transactions) {
console.log('amount:', amount);

const Transaction_str = $('<li></li>').appendTo('#list');

Transaction_str.addClass(amount < 0 ? 'minus' : 'plus');
Transaction_str.html(`${name}<span> ${amount}</span><button class="delete-btn" data-id="${id}">x</button>`);
$('#list').append(Transaction_str);


$('#text').val('');
$('#amount').val('');

//刪除鈕 要交易交出後再綁事件
$('.delete-btn').last().click(function () {
$(this).parent().remove();
let id = $(this).data('id');
//console.log(id);
deleteFromLocalstorage(transactions, id); //要記得傳入id

});

}
//從localstorage刪除
//要記得在參數放入id
function deleteFromLocalstorage(transactions, id) {
transactions.forEach(function (item, index, arr) {
//console.log('item', item);
//console.log('index', index);
//console.log('arr', arr);
if (item.id === id) {
arr.splice(index, 1);
}
});
//迴圈刪除後,要儲存到localStorage才有確實刪去
localStorage.setItem('Transactions', JSON.stringify(transactions));
}


// Generate random ID
function generateID() {
return Math.floor(Math.random() * 100000000);
}


//數值更新計算
function updateValue(transactions) {
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})

console.log(amounts_arr);

//計算加總
var total = 0;
$.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
//傳回YOUR BALANCE
$('#balance').text(`$${total}`);
console.log(total);


//*************************** */
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);

var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);
//***************************** */
//從陣列找出<0的值,放置income
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


}

//init
function initHistory(transactions) {
transactions.forEach(transaction => {
addTransactions(transaction.id, transaction.name, transaction.amount, transactions);
});
updateValue(transactions);

}


各項目拆解:

add transations按下去之後,頁面不刷新,直接將資料傳入紀錄中

1
2
3
4
5
6
$(document).ready(function () {
$('.btn').click(function () {
console.log('click');
})
});
//點擊後,有印出click,但很快的刷新頁面
  • 加入e.preventDefault(); 用來阻止預設動作的發生

讓transation輸入後顯示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$(document).ready(function () {
$('.btn').click(function (e) {
e.preventDefault();
console.log('click');
addTransactions('cash', '200');
})
});


function addTransactions(name, amount) {
var Transaction_str = `<li class='plus' >${name}<span> ${amount}</span><button class="delete-btn">x</button></li>`
$('#list').append(Transaction_str);
}

//

  • 提交之後清空
    • 選擇該輸入框,並利用val(),使內部的值清空
1
2
3
$('#text').val('');
$('#amount').val('');

從表格中取得值

  • 製作按鈕的點擊事件,取得表格中的值
  • 將值傳入函式的參數addTransactions(text_val, amount_val);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $(document).ready(function () {
    $('.btn').click(function (e) {
    e.preventDefault();
    console.log('click');

    //取得表格中的值
    const text_val = $('#text').val();
    const amount_val = $('#amount').val();
    addTransactions(text_val, amount_val);
    })

    });

製作刪除紐

  • 原本的撰寫方式,為選到最後一個刪除鈕,並點擊加以刪除
  • 此方式造成,無法確實刪除資料
1
2
3
4
$('.delete-btn').last().click(function () {
console.log('del');
})
}

  • 修改方式,只能綁定一筆transatin或是綁定最後一筆

  • 查看若實現點擊後刪除,是會刪除什麼?

    1
    2
    3
    4
     $('.delete-btn').last().click(function () {
    console.log(this);
    })
    }

  • 要刪除的是整筆資料,所以要去尋找他鄰近的元素

    1
    2
    3
    $('.delete-btn').last().click(function () {
    $(this).parent().remove();
    })

localstorage 執行

筆記補充:LocalStorage介紹

從此實作,可以看到它是一個陣列,裡面是物件

  • 設置一個空陣列
  • 並將物件push進去
1
2
3
4
5
6
7
8
9
10
//預設值的設置,取得存在本地的資料或是空陣列
var transactions = JSON.parse(localStorage.getItem('Transactions')) || [];

//推入陣列
transactions.push({
name: text_val,
amount: amount_val
})
localStorage.setItem('Transactions', JSON.stringify(transactions));

  • 增加初始function
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //init
    function initHistory(transactions) {
    transactions.forEach(transaction => {
    addTransactions(transaction.name, transaction.amount);
    });

    }

    //將此函式放於 $(document).ready()之中

    //陣列初始
    if (transactions.length > 0) {
    initHistory(transactions);
    }

將transation刪除後,並沒有完全從localstorage刪除

運用id來刪除

  • 從此段落:localstorage 執行,圖片中的存取陣列可以看到,沒有設置id

  • id是在addTransactions使用

    1
    2
    3
    4
    5
    6
    7
    8
    // Generate random ID
    function generateID() {
    return Math.floor(Math.random() * 100000000);
    }

    //floor:無條件捨去
    //ceil:無條件進位

  • 在創造的陣列中\物件,都加入id

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const id = generateID();
    addTransactions(id, text_val, amount_val);

    //推入陣列
    transactions.push({
    id: id,
    name: text_val,
    amount: amount_val
    })

  • 在addTransactions的函式中也要加入id

    1
    2
    3
    4
    function addTransactions(id, name, amount) {

    console.log(id, name, amount);}

  • 在button加入data-id

和資料有關的時候:data-原來欄位名稱

1
const Transaction_str = `<li class='plus' >${name}<span> ${amount}</span><button class="delete-btn"  data-id="${id}">x</button></li>`

  • 確定點擊刪除鈕的時後,是有抓到該id
    1
    2
    3
    4
    5
    6

    $('.delete-btn').last().click(function () {
    $(this).parent().remove();
    let id = $(this).data('id');
    console.log(id);
    })
  • let id = $(this).data(); 查看id時 取得的是物件
  • 應改為

此時還沒有真正刪除id,只是確定有抓到id :point_up_2:

jquery data(): 自定義屬性 (data attributes),讓我們可以任意讀寫資料在元素上,而且不會影響頁面的 layout
jQuery Data

  • 利用forEach、splice()刪除陣列內的資料

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function deleteFromLocalstorage(transactions, id) {
    transactions.forEach(function (item, index, arr) {
    //console.log('item', item);
    //console.log('index', index);
    //console.log('arr', arr);
    if (item.id === id) {
    arr.splice(index, 1);
    }
    });
    //迴圈刪除後,要儲存到localStorage才有確實刪去
    localStorage.setItem('Transactions', JSON.stringify(transactions));
    }
    ````


    * 查看迴圈的資料
    ![](https://i.imgur.com/FexS5lt.png)


    * 確實刪除存在localstorage的資料
    ```javascript
    localStorage.setItem('Transactions', JSON.stringify(transactions));

判斷輸入的數字大小,並給予class

  • 放在addTransactions()函式之中
1
2
3
4
5
6
const Transaction_str = $('<li></li>').appendTo('#list');

Transaction_str.addClass(amount < 0 ? 'minus' : 'plus');
Transaction_str.html(`${name}<span> ${amount}</span><button class="delete-btn" data-id="${id}">x</button>`);
$('#list').append(Transaction_str);

數值的更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function updateValue(transactions) {
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})

console.log(amounts_arr);

//計算加總
var total = 0;
$.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
//傳回YOUR BALANCE
$('#balance').text(`$${total}`);
console.log(total);


//*************************** */
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);
var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

//console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);
//***************************** */
//從陣列找出<0的值,放置income
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


}
  • 創造一個amount的陣列
1
2
3
4
5
const amounts_arr = transactions.map(function (transaction) {
return transaction.amount
})
console.log(amounts_arr);

  • 計算加總數值
    1
    2
    3
    4
    5
    6
    var total = 0;
    $.each(amounts_arr, function () { total += parseFloat((this)) || 0; });
    //傳回YOUR BALANCE
    $('#balance').text(`$${total}`);
    console.log(total);

  • income 收入加總計算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//從陣列找出>0的值,放置income
//console.log(amounts)
var income = amounts_arr.filter(
function (item) {
return item > 0
}
)
console.log(income);
var totalIncome = 0;
$.each(income, function () { totalIncome += parseFloat((this)) || 0; });

//console.log(totalIncome); //回傳220
//傳回到income
$('#money-plus').text(`$${totalIncome}`);

  • expense支出加總
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//從陣列找出<0的值,放置expense
var expense = amounts_arr.filter(
function (item) {
return item < 0
}
)
console.log(expense);

var totalExpense = 0;
$.each(expense, function () { totalExpense += parseFloat((this)) || 0; });

console.log(totalExpense);
//傳回到expense
$('#money-minus').text(`$${totalExpense}`)


錯誤修正:

  • 調換推入陣列以及addTransactions的順序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//點擊按鈕的事件
$('.btn').click(function (e) {
e.preventDefault();
//console.log('click');
//取得表格中的值
const text_val = $('#text').val();
const amount_val = $('#amount').val();
let id = generateID();

//推入陣列
transactions.push({
id: id,
name: text_val,
amount: amount_val
});

addTransactions(id, text_val, amount_val, transactions);




localStorage.setItem('Transactions', JSON.stringify(transactions));

updateValue(transactions);
})
  • 將updateValue()放入事件中
1
2
3
4
5
6
7
8
//刪除鈕 要交易交出後再綁事件
$('.delete-btn').last().click(function () {
$(this).parent().remove();
let id = $(this).data('id');
//console.log(id);
deleteFromLocalstorage(transactions, id); //要記得傳入id
updateValue(transactions);
});

實作需求分析

  • 抓取api提供的匯率資料:使用jQuery,ajax
  • 選擇不同幣別,進行匯率換算
  • swap按鈕,使幣別交換

完成後的成品

jQuery.ajax 使用

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
method: "get",
url: "https://v6.exchangerate-api.com/v6/06f04b805743079a1966771a/latest/USD",

})
.done(function( some_data ) {
console.log(data);
//成功抓到值的話,就會印出抓取到的資料
}).fail(function(){

})

  • 應用於exchangeRate:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $.ajax({
    url: `https://v6.exchangerate-api.com/v6/06f04b805743079a1966771a/latest/${currency_one}`, //注意符號
    method: 'get',//get,post,put
    dataType: 'json',
    success: function (data) {
    //console.log(data);
    const rate = data.conversion_rates[currency_two];
    //console.log(rate);
    $('#rate').text(`1 ${currency_one} = ${rate} ${currency_two}`);
    $('#amount-two').val((amountOne * rate).toFixed(2));
    }
    })

  • 詳細說明可以參照內文:計算匯率calculate函式

其他參考資料:

[ Alex 宅開發 ] 👨‍💻從 jQuery 入門到認識 JavaScript #5 Ajax 與非同步功能操作與原始碼探索

1
2
3
4
- `url`:來源,api的位置在哪裏
- `type`:api的呼叫方式
- `dataType`:它回給你的資料類型
- `data`:你要傳給它什麼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


$.ajax({
url: data.json,
type: 'get',//get,post,put,path,delete
dataType: 'json', //html,xml,text,jsonp
data: {}

}).then(function (res) {
//response <-> request
console.log(res);
return def.resolve();
}), function (err) {
console.log(err);
return def.reject();
}

計算匯率calculate 函式

  • 此函式為抓取匯率api的資料並帶入計算匯率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function calculate() {

var currency_one = $("#currency-one").val();
var currency_two = $('#currency-two').val();
var amountOne = $('#amount-one').val();
var amountTwo = $('#amount-two').val();

//https://app.exchangerate-api.com/dashboard/confirmed

$.ajax({
url: `https://v6.exchangerate-api.com/v6/06f04b805743079a1966771a/latest/${currency_one}`,//注意符號
method: 'get',//抓取值
dataType: 'json',
success: function (data) {
//console.log(data); //查看抓到的物件

const rate = data.conversion_rates[currency_two];
//console.log(rate);

$('#rate').text(`1 ${currency_one} = ${rate} ${currency_two}`);

//將值帶入
$('#amount-two').val((amountOne * rate).toFixed(2));
}
})


}

函式說明:

1.先將要抓取的值,宣告變數;分別有選擇的國家幣別、兌換的數量

2.串接資料

(1). 抓取資料的位置
url: https://v6.exchangerate-api.com/v6/06f04b805743079a1966771a/latest/${currency_one}

注意網址:
"https://v6.exchangerate-api.com/v6/06f04b805743079a1966771a/latest/USD"
注意網址後面有修改,要抓取會變動的變數: ${currency_one}

(2) 檢查是否有抓到要的資料:

  • 宣告:const rate = data.conversion_rates[currency_two];
  • console.log(rate);

  • 確定抓取的值是否正確:console.log($('#amount-two').val());

  • 將計算匯率帶入
    $('#amount-two').val((amountOne * rate).toFixed(2));

其他輸入值的抓取與連動

  • #currency-one的改變,會連動上面的函式計算結果

1
2
3
4
$("#currency-one").change(function () {
$("#rate").html("");
calculate();
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//抓取amountone
$("#amount-one").on("input", function () {
$("#rate").html("");
calculate();
})

$("#currency-two").change(function () {
$("#rate").html("");
calculate();
})

//抓取amountTwo
$("#amount-two").on("input", function () {
$("#rate").html("");
calculate();
})
  • 發現使用.append(),會出現累積div文字的問題

  • (1) 清除函式.append(),累積div文字呈現的問題
    $("#rate").html("");

  • (2) 將原本使用.append()的地方,修改為.text(), $('#rate').text(`1 ${currency_one} = ${rate} ${currency_two}`);

swap按鈕 (使幣別交換)

  • 宣告一個變數,紀錄交換前的幣別let temp = $("#currency-one").val();
  • 確認是否宣告正確:console.log(temp);

1
2
3
4
5
6
7
8
9
//swap按鈕
$('#swap').click(function () {
let temp = $("#currency-one").val();//設一個變數來存放currency-one
$("#currency-one").val($("#currency-two").val());
$("#currency-two").val(temp);
calculate();
})

calculate(); //放於最後
  • console.log($("#currency-one").val());
  • console.log($("#currency-two").val());


參考資料:
重新認識 JavaScript: Day 16 那些你知道與不知道的事件們

1. DOM 與樹狀結構

  • DOM: document:網頁內部

    KURO 老師:
    DOM 是一個將 HTML 文件以樹狀的結構來表示的模型,而組合起來的樹狀圖,我們稱之為「DOM Tree」。

Huli 老師:瀏覽器提供該橋樑,讓我們用js去改面畫面的東西

API (Application Programming Interface)

  • 應用程式 編程 介面

    document 物件 API 文件

  • getElementsByTagName : 抓取html中某tag的元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html lang="en">
    <body>
    <div>
    hello~

    </div>
    <div>
    yo!
    </div>
    <script>

    const elements = document.getElementsByTagName('div');
    console.log(elements);
    </script>
    </body>
    </html>

  • getElementsByClassName: 抓取html中某class元素(有好幾個相同名稱的class,會一並抓取)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>

<body>
<h1>DOM
</h1>
<div class="block1">
hello~

</div>
<div>
yo!
</div>
<script>

const elements = document.getElementsByClassName('block1');
console.log(elements);
</script>
</body>

</html>

  • getElementById : 注意:getElement 沒有加s!這是用來抓取指定ID

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <body>
    <h1>DOM
    </h1>
    <div class="block1">
    hello~

    </div>
    <div id="myyo">
    yo!
    </div>
    <script>
    const elements = document.getElementById('myyo');
    console.log(elements);
    </script>
    </body>

  • querySelector: 後面接的是css選擇器

  • 只會針對元素的第一筆資料,其他並不會被選入這時候可以使用

    • 選擇tag標籤:(‘div’):注意:使用此方式當html有多個div,他只會選擇到第一個符合的
    • 選擇cass : (‘.calssName’)
    • 選擇id : (‘#idName’)

  • 也可以選區某一tag下的tag

    • querySelector('div > a')
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      <body>
      <h1>DOM
      </h1>
      <div class="block1">
      hello~

      </div>
      <div id="myyo">
      yo!
      <a href="#">hello</a>
      </div>
      <script>

      const elements = document.querySelector('div > a');
      console.log(elements);
      </script>
      </body>
  • querySelectorAll: 可以選取多個元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<h1>DOM
</h1>
<div class="block1">
hello~

</div>
<div id="myyo">
yo!
<a href="#">hello</a>
</div>
<script>

const elements = document.querySelectorAll('div');
console.log(elements);
</script>

Eloquent JavaScript, 3rd Edition

順利選則元素之後,嘗試做些改變

可以看看,js如何與瀏覽器互動 ->JavaScript 與瀏覽器的溝通

BOM 與 window 物件

  • BOM (Browser Object Model,瀏覽器物件模型),是瀏覽器所有功能的核心,與網頁的內容無關。
    • window是瀏覽器的根物件,也是BOM的瀏覽器模型
  • window.location.hrrf => 可以知道現在網址
  • window.history.back(); => 回到網頁瀏覽的上一頁

參考資料

Day03-深入理解網頁架構:DOM
JS 筆記 - 認識 DOM 文件物件模型
MDN-Document
The HTML DOM Document Object
JavaScript 基礎知識-querySelectorAll
The Document Object Model
JavaScript入門系列:BOM和DOM筆記

程式柴

Function、array都屬於物件

物件的例子

1
2
3
4
5
6
7
8
9
var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interest: ['music', 'movie'],
greeting: function () {
console.log('hi I\'m' + this.name[0] + '.');
}
}

物件的創建

var x={}

  • 有一隻狗,其名字、年齡,函式
    1
    2
    3
    4
    5
    6
    7
    8
    var dog = {
    name: 'tracy',
    age: 20,

    bow: function () {
    console.log('bow!bow!');
    }
    }
  • 用.呼叫屬性,或是dog[‘key’] :point_down:
  • 物件內的函式

添加屬性至物件上

  • 增加值的方式

    • dog.color = 'white';
    • dog['size'] = 'small'; =>較常用
  • 增加函式 => 一樣用.的方式

    • dog.bowbow = function () { console.log('bow!bow!~~') }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var dog = {
name: 'tracy',
age: 7,
bow: function () {
console.log('bow!');
}
}

//增加值的方式
//1
dog.color = 'white';
dog.eyes = 'big';
//2
dog['size'] = 'small';
//增加函式
dog.bowbow = function () {
console.log('bow!bow!~~')
}

陣列

程式柴

  • 陣列用 中括號[ ]

  • 陣列的計算是從零開始(取陣列的索引)

    • 呼應for 迴圈,從0開始,從索引第一個
      1
      2
      3
      4
      arr = [111, 222, 333]
      console.log(arr);
      console.log(arr[1]); //222
      //呼應for 迴圈,從0開始,從索引第一個
  • 陣列中的東西都是相同屬性,比較好操作

    1
    2
    3
    arr2 = ['dog', 'cat', 'sth']
    console.log(arr.length); //3
    arr3 = [111, 'cat', 'sth']

  • 練習:要紀錄10位學生的分數,並加總

    1
    2
    var score = [1, 3, 4, 5, 100];
    console.log(score);

    陣列基本操作 -> poppush 較常用

  • score.push(1000) -> 新增元素到現有陣列中,加入尾端

  • score.unshift(888) -> 加入陣列最前面

  • pop:從最末端抽走元素

1
2
3
4
5
6
7
var myHeros=['孫悟空', '佐助', '女超人', '美國隊長'];
//從最末端抽走元素
myHeros.pop();

//從頭抽走元素
myHeros.shift();
console.log(myHeros);

陣列替換元素

  • 在原本陣列中,選取要取代的該元素,後面加=,並輸入內容

陣列取得最後一個元素

  • 該陣列長度-1,就可以取得最後一個元素
    • 長度為七,最後一個的索引是6 :point_down:

用 indexOf 取得元素的索引

  • Of的o要大寫
1
2
3
4
var myHeros=['孫悟空', '佐助', '女超人', '美國隊長'];
//檢查誰誰誰有在陣列中嗎
console.log(myHeros.indexOf('達爾')); //印出-1,意指此元素不存在陣列中
console.log(myHeros.indexOf('美國隊長')); //印出3(在陣列中第幾個索引

切片 slice 與方法

1
2
3
4
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
//用索引
console.log(arr.slice(2, 4));//不包含最後一個
console.log(arr.slice(2, 5));

  • 複製陣列
    1
    2
    var shallowCopy = fruits.slice(); // 這就是複製陣列的方式
    // ["Strawberry", "Mango"]

MDN slice
MDN array
JavaScript Array 陣列操作方法大全 ( 含 ES6 )

陣列與物件

  • 例子:被老師要求要記錄,學生的名字,分數,地址…

  • 以陣列的想法,會將各類別分類,放入同屬性的結果

    • 學生的分數,名字個一個陣列
    • 要取得同一位學生的所有資料,要個別從矩陣中拿取
  • 一個資料集合,就能代表一個學生 –>物件

    • 以下面的資料結構來代表學生的一些屬性

補充

  • 物件與陣列,與等號的關係,理解
    • 下方的結果都是false

因為:

  • var obj=[a:1],會將它放在某一個記憶體位置
  • var obj2=[a:1],會將它放在另一個記憶體位置

PS:即便內容,數值一樣,但js判斷的是記憶體位置不一樣

使用函式可以讓我們執行效率提升,不用重複撰寫,只需幾行語法便可以達到快速的運算、或是功能的執行。以下範例為數羊計數,透過函式以及迴圈,以幫助設定計數的起始以及終點,並快速的執行範圍內的計數。

1
2
3
4
5
6
7
8
//為什麼我們需要function
//DRY -> Don't repeat yourself
function echoSheep(index) {
console.log('第' + i + '隻綿羊')
}
for (var i = 1; i < 11; i++) {
echoSheep(i)
}
  • 與過去所學結合

  • 也可以return後面接物件
    • 回傳結果為20

簡單練習題

  • 創建空陣列,並於陣列中放數1,2,3,…10


要放入return,否則會出現undefined

  • 也可以將參數改成兩個數
1
2
3
4
5
6
7
8
function generateArray(a, b) {  //a,b 可以改為 from,to
var result = [];
for (var i = a; i <= b; i++) {
result.push(i);
}
return result;
}
console.log(generateArray(3, 10))

return

  • 函式中一放進return,在函式,return後面的部分就不會運行了

  • 不需要知道結果

  • 需要回傳值

  • 參數:函式後面要傳入的值
  • 引數:真正傳進去的東西

  • Arguments:為類陣列,屬於物件

表達式(Expression)與陳述句(Statement)的差異

  • 表達式:會回傳值
  • 陳述句:不會回傳值 (if…else,switch,等控制流程)

使用函式陳述式(Function Statement)與函式表達式(Function Expression)

  • 函式陳述式(Function Statement):在使用函式之前,放入helloFunctionStatement();是可以執行
1
2
3
4
5
6
7
//helloFunctionStatement();  放在前面沒關係
function helloFunctionStatement() {
console.log('this is Function Statement ');

}

helloFunctionStatement();
  • 函式表達式(Function Expression):反之,要放在宣告之後
    1
    2
    3
    4
    5
    6
    //helloFunctionExpression(); 放前面,會出現錯誤
    var helloFunctionExpression = function () {
    console.log('this is Function Expression ');

    }
    helloFunctionExpression();
    :::warning
    因為hoisting(變數提升)的關係
    :::

JS 原力覺醒 Day07 - 陳述式 表達式

變數能夠影響的範圍作用域( Scope 作用域:變數可以影響的範圍 )

  • 在function中,所宣告的 var a = 50;,範圍就只有涵蓋在函式中,不會影響到外面
1
2
3
4
5
6
7
var a = 100;
function helloWorld() {
var a = 50;
console.log(a);
}
helloWorld();
console.log(a);

  • 如果函式中,宣吿某變數,沒有加var/let,該變數就會影響外部
    1
    2
    3
    4
    5
    6
    7
    var a = 100;
    function helloWorld() {
    a = 50;
    console.log('function:', a);
    }
    helloWorld();
    console.log('外部:', a);

全域變數與區域變數

  • 使用var,let,const,來宣告

  • 全域變數:在瀏覽器中,沒有在fuction裡,直接進行宣告

    • 也可以用window來存取
    • window,是瀏覽器上的根物件
1
2
3
4
5
var y = 1;  //在外面宣告為 全域變數
function abc() {
//var,let,const
var x = 1
}
  • 區域變數:在function中進行宣告

    1
    2
    3
    4
    function abc() {
    //var,let,const
    var x = 1
    }
  • 不是變數 => 全域的屬性

    • z=1;
    • 也可以用window來存取

回呼函數 Callback Function

  • 把函數做為參數傳遞
  • 當檔案讀取完畢時,請來執行這個 function,並且把結果傳進來
  • heyFunc(console.log)->console.log 可以替換別的
1
2
3
4
5
function heyFunc(myFunction) {
myFunction('hi');
myFunction('hi');
}
heyFunc(console.log);

  • 非同步(Asynchronous):回呼常用來延續非同步行動完成後的程式執行

其他介紹 超入門 JavaScript 教學 13 - 回呼函式 callback

  • 以下範例:讓cb接到shout這個函式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function shout() {
    console.log('hello,i am done')
    }
    function countToSeven(cb) {
    for (var i = 1; i <= 7; i++) {
    console.log(i);
    }
    if (typeof cb === 'fuction')
    cb(); //啟動shout函式
    }
    countToSeven(); //會數1-7
    //要數完七之後,說'hello,i am done
    countToSeven(shout);
    countToSeven(1);//1不是函式,所以在if判斷句終止

    //每隔一段時間,幫我做一次
    setInterval(shout, 2 * 1000);//每隔兩秒執行sout
    //在多少時間之後,幫我執行
    setTimeout(shout, 1 * 1000)

    js內建函式

    • 每隔一段時間,幫我做一次
      setInterval(shout, 2 * 1000);//每隔兩秒執行sout
    • 在多少時間之後,幫我執行
      setTimeout(shout, 1 * 1000)

參考資料:

重新認識 JavaScript: Day 18 Callback Function 與 IIFE
JavaScript 中的同步與非同步(上):先成為 callback 大師吧!
JS20min Day — 18 關於回呼生活化 (Callback)

匿名函式

  • heyFunc裡面的function沒有名稱
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function heyFunc(myFunction) {
    myFunction('hi');

    }
    heyFunc(function (message) {
    console.log('message is:', message);
    });
    //message is:hi
    </script>

立即函式(IIFE)

Luka

  • 它是沒有名字的函式,要立即調用
    • 不讓函式內的變數污染到外面的東係
    • 讓jquery的$$變成是jquery使用
      1
      2
      3
      4
      5
      (function (name) {
      var str = 'Hi ' + name + '!';
      console.log(str);
      })('Sam');

  • 一般常見寫法
    1
    2
    3
    4
    5
    var sayHi = function (name) {
    var str = 'Hi ' + name + '!';
    console.log(str);
    }('Peter')//在後面立即執行
    // sayHi("Peter");

[筆記] 談談JavaScript中的IIFEs(Immediately Invoked Functions Expressions)
[筆記] 為什麼我們要用IIFEs(Immediately Invoked Functions Expressions)

hoisting 變數提升淺談

  • js的變數與函式的宣告提升

  • 不管在哪一行使用了變數,都視為第一行宣告

    比較好的流程 By 彭彭

但在js有hoisting 變數提升

  • 就算把變數宣告放在後面,依然可以運作(會將var x提升到最前面)

進一步細節…


電腦解讀如下

  • var x會提升


    結果會印出undefined

在函示fuction的變數提升

  • 先宣告函式,在能呼叫函式執行

  • 在js先呼叫,依然可以運作

其他狀況…(把函式裝到變數中當作資料)

  • 在此情形,它會出現錯誤,回報test不是一個函式

  • 程式的解讀 :point_down:
  • 只有var test被提升

程式柴

  • 沒有宣告

常用的內建函式

Number類型

  • 字串轉數字

  • parseInt 是取整數,若遇到如20.35,就只會取到20

  • 遇到小數點且要保留的時候,使用parseFloat
    • 結果為30.35

  • Math.ceil()=> 無條件進位
  • Math.floor()=> 無條件捨去
  • Math.round() => 四捨五入
  • Math.sqrt() => 開根號
  • Math.pow() => 次方
  • Math.radom() => 產生隨機數(0-1,不包含1)
  • toString() => 數字轉字串
    • 或是加空字串

String類型

  • toUpperCase=> 轉大寫

  • toLowerCase => 轉小寫

  • indexOf => 找出字串中,單字的索引(用於檢查某字是否存在字串中)

  • replace() => 取代

    • 用正規表達式來選擇 某些字

  • split() => 切字串

    1
    2
    3
    4
    //split較常使用的情形
    //當資料為一連串字串,利用逗號切割 變成陣列,比較好運用
    var str = 'data1,data2,data3,data4';
    console.log(str.split(','));

  • trim() =>從一個字符串的两端刪除空白字符

    1
    2
    3
    4
    5
    6
    7
    const greeting = '   Hello world!   ';

    console.log(greeting);
    // expected output: " Hello world! ";

    console.log(greeting.trim());
    // expected output: "Hello world!";

Array 類型

  • Array.prototype.join()
  • 方法會將陣列(或一個類陣列(array-like)物件)中所有的元素連接、合併成一個 ‘字串’,並回傳此字串(在陣列中每個元素間插入設定的東西)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const elements = ['Fire', 'Air', 'Water'];

    console.log(elements.join());
    // expected output: "Fire,Air,Water" //會變成字串

    console.log(elements.join(''));
    // expected output: "FireAirWater"

    console.log(elements.join('-'));
    // expected output: "Fire-Air-Water"
  • Array.prototype.map()
  • 建立一個新的陣列,其內容為原陣列的每一個元素經由回呼函式運算後所回傳的結果之集合。
    1
    2
    3
    4
    5
    6
    var arr = [1, 2, 3];
    console.log(
    arr.map(function (x) {
    return x * -1
    })
    )
1
2
3
4
5
6
7
8
9
10
11
//也可以接著寫下去
var arr = [1, 2, 3];
console.log(
arr
.map(function (x) {
return x * -1
})
.map(function (x) {
return x * 2
})
)

  • Array.prototype.filter()

  • 過濾

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var arr = [1, 2, 3, -5, 3, -2];
    console.log(
    arr
    .map(function (x) {
    return x * 2
    })
    .filter(function (x) {
    return x > 0
    })
    //把負數過濾掉,留下正數
    )

  • Array.prototype.slice()

  • Array.prototype.splice()

    • splice 1.插入元素
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      const months = ['Jan', 'March', 'April', 'June'];
      months.splice(1, 0, 'Feb');
      // inserts at index 1
      console.log(months);
      // expected output: Array ["Jan", "Feb", "March", "April", "June"]

      months.splice(4, 1, 'May');
      // replaces 1 element at index 4
      console.log(months);
      // expected output: Array ["Jan", "Feb", "March", "April", "May"]

  • splice 2.刪除元素

    1
    2
    3
    4
    5
    var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
    var removed = myFish.splice(3, 1);

    // removed 為 ["mandarin"]
    // myFish 為 ["angel", "clown", "drum", "sturgeon"]
  • Array.prototype.sort()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const months = ['March', 'Jan', 'Feb', 'Dec'];
    months.sort();
    console.log(months);
    // expected output: Array ["Dec", "Feb", "Jan", "March"] //按照第一個字母順序排列

    const array1 = [1, 30, 4, 21, 100000];
    array1.sort();
    console.log(array1);
    // expected output: Array [1, 100000, 21, 30, 4] //是一字串,以第一個數字來排列

  • 依照數字大小排列

    1
    2
    3
    4
    5
    6
    7
    var arr = [1, 30, 4, 2];
    arr.sort(function (a, b) {
    if (a === b) return 0;
    if (b > a) return -1; //不換
    return 1; //正數,換位置
    })
    console.log(arr);

「回傳」與「印出」的差異

  • 函式可以透過 return 回傳函式運算完的結果

    述程式碼的執行:

1.console.log(add(1, 2)) => 帶入functoin,console.log(a, b); => 印出1,2
2.往下,到return undefined; 然後進入add(1, 2)的回傳值,就會是undefined

1
2
3
4
5
6
7
8
function add(a, b) {
console.log(a, b);
return undefined; //不加return,預設會是undefined
}

console.log(add(1, 2))


  • 以為 add(1, 2) 的回傳值是 3,但不是,那是因為它在裡面 console.log() 所以把結果印出來了。
    1
    2
    3
    4
    function add(a, b) {
    console.log(a + b)
    }
    add(1, 2)
  • 如果真的要有回傳值的話要這樣寫:
    1
    2
    3
    4
    function add(a, b) {
    return a + b
    }
    console.log(add(1, 2))

參考資料: JavaScript 初心者筆記: 函式實際運作 - 回傳值與函式間互相傳遞
,後設鐵人 Day4:請幫我簽個名好嗎?

Immutable 觀念 (不可變)

  • 除了物件、陣列以外,其他都是不可變的
  • 沒辦法改它,就只能回傳新的
    1
    2
    3
    4
    var a = 'hello';
    a.toUpperCase;
    console.log(a);
    //印出:hello,沒有改變原本變數的內容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a = 'hello';
    a = a.toUpperCase(); //要回傳給a,把原本的a值蓋掉
    console.log(a);

    //或是增設一個新變數
    var a = 'hello';
    var b = a.toUpperCase();
    console.log(b);

簡易控制流程的撰寫

1
2
3
4
5
6
7
8
9
10
var str = '只被當一科';
if (str === 'all pass') {
console.log('帶你去歐洲玩');
} else if (str === '只被當一科') {
console.log('帶你去宜蘭玩');
} else {
console.log('禁足');
}
//帶你去宜蘭玩

使用switch來撰寫(太多如果的話可以改用switch)

  • 使用break,是用來跳出swich迴圈(換句話說,沒有寫break的話會使程式一直往下跑)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //用switch 改寫 if else
    var key = 'all pass';
    switch (key) {
    case 'all pass':
    console.log('帶你去歐洲玩');
    break;
    case '只被當一科':
    console.log('帶你去宜蘭玩');
    break;

    default:
    console.log('禁足');
    break;
    }
    // 帶你去歐洲玩

迴圈基本介紹

loop:一直做一樣的事情
無窮迴圈,發生的情形:沒有設終止條件,或是終止條件設錯 (control+c 終止它)

  • 可在程式最前面,加入debugger

1.迴圈for

彭彭的課程

用 for 迴圈數綿羊數到一百隻,直到睡著

  • var後面宣告的變數,可以替換不同字母
    1
    2
    3
    4
    5
    6
    7
    // for(初始值;終止條件;每次執行的語句)
    for (var i = 0; i < 100; i++) {
    console.log("第" + (i + 1) + "隻綿羊");

    }
    //會印出1~9
    //i++ 意思指 i+=1 ,也是i=i+1

    用 for 迴圈倒著數綿羊

    1
    2
    3
    4
    5
    6
    for (var k = 100; k > 0; k--) {
    console.log("第" + k + "隻綿羊");
    if (k === 1) {
    console.log('睡著了!');
    }
    }

    用 for 迴圈 數到第 31 隻綿羊就睡著了! (break)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (var i = 1; i <= 100; i++) {
    console.log("第" + i + "隻綿羊");
    if (i === 31) {
    console.log('睡著了!');
    break;
    }
    if (i === 10) {
    console.log('覺得想睡了!'); //到10不會停止
    }
    }

    用 for 迴圈 跳著數

  • 奇數 -> 對2取於數為1者

    1
    2
    3
    4
    5
    6
    for (var i = 1; i <= 10; i++) {
    if (i % 2 === 1) {
    console.log("第" + i + "隻綿羊");
    }

    }
  • 印出1,4,7,10

    1
    2
    3
    4
    5
    for (var i = 1; i <= 10; i++) {
    if (i % 3 === 1)
    console.log("第" + i + "隻綿羊");

    }

用 for 迴圈 我只想跳過第四隻綿羊

  • 使用continue:會跳過一次(跳過設定的條件),然後繼續下一次迴圈
  • 注意語法的順序,如果console.log()在if..continue之前,會變成先讀取所有的i,不會跳過指定位置
1
2
3
4
5
6
7
for (var i = 1; i <= 10; i++) {
if (i === 4) {
continue
}
console.log("第" + i + "隻綿羊");

}

for與陣列的搭配

  • i是依照索引來計算,故應該是要0,1,2,3,4 => <5
    • 最後一個索引值是4(第5個沒有值)

2.迴圈while

透過彭彭的課程來認識迴圈while

迴圈思考方式:

彭彭的課程

1
2
3
4
5
6
7
8
//1+2+...+50 的運算流程 
var sum=0;
var n=1;
while (n<=50){
sum=sum+n;
n++
}
alert(sum);

方式:

和迴圈相關的變數追蹤(sum,n)

第0次迴圈:先判斷n是否<=50
sum:0 ,n:1
第1次迴圈:
sum:1,n:2
第2次迴圈:先判斷n是否<=50 (根據上一個n是2)
sum:(1+2)=3,n:3
第3次迴圈:
sum:(3+3)=6,n:4

第50次迴圈:
sum:1275,n:51
第51次迴圈:因大於50,故跳離回圈結束

延續上面的思考,加入continue

1
2
3
4
5
6
var x=0;
for(var i=0;i<100;i++){
if(1%2= = =0){continue}
x++
}
alert(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
變數追蹤(x,i)
0:
x:0,i:0
1:
x:0 (i為0,對2取餘數為0,進入continue,然後重新開始回圈,沒有進入x++), i:1
2:
x:1(i為1,對2取餘數不為0,所以沒有執行continue,直接進入x++),i:2

3:
x:1,i:3
4:
x:2,i:4
...
100:
x:50,i:100

用 while 也可以達到相同的屬羊效果

  • 印出0~10
  • 相對for囉唆一點
1
2
3
4
5
let x = 0;
while (x < 10) {
console.log(x);
x++;
}

  • 利用console來debug

    1
    2
    3
    4
    5
    6
    7
    8
    let x = 0;
    while (x < 10) {
    //利用console來debug
    console.log(x)
    x++;
    console.log("第" + x + "隻綿羊");

    }

  • 搭配continue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let x = 0;
    while (x < 10) {
    //利用console來debug
    console.log(x)
    x++;
    if (x == 4)
    continue;
    console.log("第" + x + "隻綿羊");

    }
  • 搭配break

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let k = 0;
    while (k < 10) {

    k++;
    console.log("第" + k + "隻綿羊");
    if (k == 5)
    break;


    }

3.迴圈 do..while

  • ()放條件,{}放區塊
    1
    2
    3
    4
    5
    6
    let i = 0;
    do {
    i++
    console.log('第' + i + '隻綿羊')
    } while (i < 10)

    與while的不同

  • 因為i<10的條件在最後面,所以他會先跑完do,再到while終止
    • i++完之後,跑到while(11>10),跳出迴圈,執行console.log
      1
      2
      3
      4
      5
      6
      let i = 10;
      do {
      i++
      console.log('第' + i + '隻綿羊')
      } while (i < = 10);
      console.log('i=',i); //i=11
  • 另一種寫法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let i = 10;
    do {
    i++
    console.log('第' + i + '隻綿羊')
    if (i>10){
    break //同等於終止條件
    }

    } while (true); //如果沒有if條件,這裡又設true,此狀況下會形成無限迴圈
    console.log('i=',i); //11

  • 同樣放入while回圈,結果就不會顯示,因為一開始k=10,進入比較,就不符合條件
    1
    2
    3
    4
    5
    let k = 10;
    while (k < 10) {
    k++;
    console.log('第' + k + '隻綿羊')
    }

雙層回圈

用 99 乘法表學雙層迴圈

1
2
3
4
5
6
7
8
9
10
11
12
13
//有兩層,需數2次
for (i = 1; i < 10; i++) {

for (k = 1; k < 10; k++) {

console.log("i:" + i, "k:" + k);
// console.log(i + '*' + k + '=' + (i * k));
let result = i * k;
let str = i + "x" + k + "=" + result;
console.log(str);
}

}

參考資料:
MDN continue
重新認識 JavaScript: Day 09 流程判斷與迴圈
JS跳出循环的三种方法(break, return, continue)

比較運算子

  • 運算符號,使用>,<,=來做判斷

三個等於與兩個等於 有什麼不一樣

  • 只有一個等於:var x=1; -> 賦值運算子
  • 所以比較運算值的時候,會使用兩個等於以上

兩個等於

  • 不是嚴格的比較
  • 轉換過的值是相同的,就會符合

三個等於

  • 實務常用,且較為嚴謹
  • 字串需經過轉換為數值,進行比較

算數運算子

  • +,-, * ,/
  • 先乘除後加減
  • parseInt(10/3) ->取整數
    • 除了取整數外,也將文字轉數值

餘數與被除數

邏輯運算子

  • 用於結合流程判斷:兩件事同時發生,要兩個都符合、或是達成其中之一

AND (&&)

運算式1 && 運算式2

  • 假如 運算式1 可以被轉換成 false的話,回傳 運算式1; 否則,回傳 運算式2。 因此,&&只有在 兩個運算元都是True 時才會回傳 True,否則回傳 false。

OR(||)

運算式1 || 運算式2

  • 假如 運算式1 可以被轉換成 true的話,回傳 運算式1; 否則,回傳 運算式2。 因此,||在 兩個運算元有任一個是True 時就會回傳 True,否則回傳 false。
  • 以布林值為例
    在OR中,只要有其中一個為true,就會回傳true

  • 運算子的判斷

  • x-y 是正確的,再往下執行(y-1) 回傳1(2-1)

  • 執行x-y時,就確定它有值了,所以先行回傳3

  • 在運算式中第一個值為false,於&&,||

  • 其他範例:

z沒有設定值,就會被設定一個預設值 ->變數沒有值的時候,給他預設值
n已經有值,就會回傳他自己的值

NOT (!)

清楚介紹:MDN

三元運算子

  • 有三個運算元
  • 如果 ? 我就 : 不然 (如果我有1千萬 ? 我就 : 否則)
    • 1>=3是false,所以回傳b

  • 也同等於if else

賦值運算子與次方(+= 系列)

  • +=運算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
console.log('賦值運算子')
var x = 1;
console.log('x=', x); //1
x += 1;
console.log('x+=1 等於', x); //2
//x=x+1
var y = 10;
y -= 2;
//y=y-2
console.log(y);
x *= 5;
console.log('x*=5 等於', x); //10
x /= 2;
//x=x/2
console.log('x/=2等於', x) //5
////////////////////////
var z = 35;
z %= 10;
// z = z % 10;
console.log('z %=10', z);
  • 次方運算

1
2
3
4
//次方
/////////
var a = 2;
console.log('a **5', a ** 5); //2的5次方=32
  • 給預設值

    1
    2
    3
    4
    5
    6
    7
    var b;
    b ||= 10;
    console.log('給預設值 b', b); //回傳10

    var c = 555;
    c ||= 10;
    console.log('給預設值 c', c); //回傳555 ; 因為c有宣告,所以c適用原本給的值

使用var來宣告變數

如果var沒有給予任何值,會呈現undefine

給予值之後

程式語言中 等於符號= 不是比較的意思,是->指派值的意思
上圖:1是一個值,它指派給x這個變數

要比較值的大小

  • true,false(布林值)
  • 宣告x為1,y=2;利用 ===來判斷

型別

  • 剛剛把1給x這個變數
  • 當查看型別時,如下圖

在VS code 來撰寫 JS

  • 與剛剛在chrom一樣的方式來輸入x,y
  • 利用console.log來印出資料
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用 VS code 來撰寫 JS,講解變數,值與型別</title>
</head>

<body>
<h1>EX 01</h1>
<script>
console.log('hello world')
var x;
console.log(x); // 出現undefined
var y = 10;
console.log(y);

</script>
</body>

</html>

型別介紹:

Number 數值

  • 通常程式語言會分成,如:python’java’c…
    • 整數 integer:只需紀錄完整數字
    • 浮點數 float:小數點
  • 而javascript 不區分 -> 只有 數值number(具有浮點數能力)
  • 以下宣告 b=1.1,查看型別發現是typeof

  • 另外以python為例:可以發現有區分顯示整數、浮點數

程式柴課程:

浮點數的陷阱

  • 因為js運算是依循IEEE754的規範,在運算時會轉換成二進制,而浮點數在轉成二進制時會造成無窮迴圈,進而產生運算誤差
  • 由於js採用64位雙精度浮點數編碼,實際儲存時為了節省空間,採用科學計數法表示

參考資料:
[JavaScript]浮點數運算出現一堆小數位數 JavaScript 浮點數陷阱及解法
js浮點數計算精度問題
JavaScript-Number的各種地雷–浮點數運算

String 字串

程式柴課程:

  • 以chrome開發者工具示範

  • 單雙混用

  • ES6使用 (此符號也能用來處理斷行問題)

  • 字串連接

clear() 清除頁面

Boolean 布林值


二進位:
0的時候->false
1的時候->true

  • 搭配if、else使用,以控制或判斷流程

「null 空值」與 「undefined 未定義」

  • 宣吿了x變數,卻沒有給它值(還沒有指派給它值) ->未定義的變數

  • 期待它是一個空值,是由使用者指派給b變數(指定給它為空值)


介紹

成品
運用css可以做出許多意想不到的效果,有立體的呈現、動畫的改變等等…

  • 漢堡表單的製作,以及點選時頁面的跳轉、動畫的改變
  • nav按鈕,立體翻轉
  • 中間icon圖示的排版,以及旋轉的效果

banner區的架構

1
2
3
4
5
6
7
8
<div class="banner">
<div class="logo">
<a href="#"><img src="./hamburger-images/logo.png" alt=""></a>
</div>
<div class="btn-wrapper">
<button class="banner-btn">Explore More</button>
</div>
</div>
  • 導覽列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<nav class="top-nav">
<ul class="nav-list">
<li>
<a href="#" class="nav-link" data-text='Home'>Home</a>
</li>
<li>
<a href="#" class="nav-link" data-text='About As'>About As</a>
</li>
<li>
<a href="#" class="nav-link" data-text='Our Team'>
Our Team
</a>
</li>
<li>
<a href="#" class="nav-link" data-text='Services'>
Services
</a>
</li>

<li>
<a href="#" class="nav-link" data-text='Contanct'>
Contanct
</a>
</li>


</ul>
</nav>

  • 加入社群媒體icon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<nav class="bottom-nav">
<ul class="icons">
<li class="icon-item">
<a href="#" class="icon-link"><i class="fab fa-facebook-f"></i></a>
</li>
<li class="icon-item">
<a href="#" class="icon-link"><i class="fab fa-youtube"></i></a>
</li>
<li class="icon-item">
<a href="#" class="icon-link"><i class="fab fa-twitter"></i></a>
</li>
<li class="icon-item">
<a href="#" class="icon-link"><i class="fab fa-google-plus-g"></i></a>
</li>
</ul>
</nav>

  • 先讓nav列hidden起來

    • 再html的class後面,增加hidden,瀏覽器就不會顯示該隱藏的部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

<nav class="top-nav" hidden>
<ul class="nav-list">
<li>
<a href="#" class="nav-link">Home</a>
</li>
<li>
<a href="#" class="nav-link">About As</a>
</li>
<li>
<a href="#" class="nav-lik">
Our Team
</a>
</li>
<li>
<a href="#" class="nav-link">
Services
</a>
</li>

<li>
<a href="#" class="nav-link">
Contanct
</a>
</li>


</ul>
</nav>

</div>


  • 讓兩個a連結的nav都hidden

右上選單

先製作三個div

1
2
3
4
5
<div class="hamburger-menu">
<div class="line line-1"></div>
<div class="line line-2"></div>
<div class="line line-3"></div>
</div>
  • 在hamburger-menu這裏的寬度、高度、位置先設定好

  • 針對div的line設定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    .hamburger-menu{
    width: 35px;
    height: 30px;
    background-color: #fff;
    position: fixed;
    top: 40px;
    right: 50px;
    }

    .line{
    width: inherit;
    height: 5px;

    background-color: #16c3cf;
    border-radius: 25px;
    }
    .line-2{
    background-color: #000;
    }
  • 他是三個div組合的

  • 這裏故意把2設為黑色

  • 讓他分三條線可以分散對齊
  • 把白色去掉
    1
    2
    3
    4
    5
    6
    7
    8

    .hamburger-menu{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    cursor: pointer;
    }


3D按鈕

1
2
3
4
5
6
/* 3d按鈕 */
.banner-btn{
width: 350px;
height: 100px;
background: linear-gradient(#16c3cf,#156459);
}

  • text-shadow: 0 10px 10px #000;

參考資料:

:::success
我們會在要進行3D變形的外層容器元素來定義perspective,這樣包含在其內的子元素(物件)都可以按照這個深度來進行變形。
perspective設定為300px或更少時,會有強烈的失真,500px到1000px的失真較為中等,2000px以上的失真就很輕微。
:::

  • 要在該按鈕前面增加一個偽元素

1
2
3
4
5
6
7
8
.banner-btn::before{
content: '';
width: 100%;
height: 15px;
background-color: red;
position: absolute;

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.banner-btn::before{
content: '';
width: 100%;
height: 15px;
background-color: #156469;
position: absolute;
bottom: 0px;
right: 0px;

transform: rotateX(90deg); /*會使他消失 */

transform-origin:bottom ;

}

  • transform-style: preserve-3d;

  • transform-origin:bottom ;

  • .banner-btn::after

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.banner-btn::after{
content: '';
width: 15px;
height: 100%;
background-color: #16c3cf;
position: absolute;
top: 0px;
right: 0px;

transform: rotateY(-90deg); /*會使他消失 */

transform-origin:right;

}


nav列

  • z-index:100

  • 在上層導覽列,先設定灰色的背景,以方便看清楚大小

  • 使用flex排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.nav-list{
background-color: #ccc;
list-style: none;
width: 80%;
margin: auto;
height: inherit;

/* 使他水平 */

display: flex;
justify-content: space-evenly;
align-items:center;

}

上層導覽列,連結的3d按鈕製作

  • 在他們的html 設定data-text
    1
    2
    <li> <a href="#" class="nav-link" data-text='Home'>Home</a> </li>

1
2
3
4
5
6
7
8
.nav-link::after{
content: attr(data-text);
position: absolute;
left:0;
bottom:-100%;
background-color: #000;
padding: inherit;
}

  • 將after創造出的rotate到父層元素的下方

  • transform: rotateX(-90deg);

    1
    2
    3
    .nav-link:hover{
    transform: rotateX(90deg);
    }

位置不對:

  • transform-origin: top;


icon button

1
2
3
4
5
6
.icons{
position: absolute;
/* 父層已經有設定fixed */
top: 50%;
left: 50%;
transform: translate(-50%,-50%);

1
2
3
4
5
6
7
.icons{
display: flex;

width: 60%;
justify-content: space-between;

}

  • 上面因為原本為inline元素, display:blockdisplay:flex

  • 要使icon在中間,使用flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.icon-link{
width: 200px;
height: 200px;

border:8px solid #fff ;

display: flex;
justify-content:center;
align-items: center;

text-decoration: none;

border-radius: 5px; }

  • 調整height

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.icon-link::before{
content: '';
height:25px ;
width: 5px;
background-color: #fff;
position: absolute;
top: 0;


}

.icon-link::after{
content: '';
height:25px ;
width: 5px;
background-color: #fff;
position: absolute;
bottom: 0;


}

背景顏色的動畫

1.在icon後面增設背景色彩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.icon-item:nth-child(1) .icon-link i::after{
background-color: #3b5999;
}

.icon-item:nth-child(2) .icon-link i::after{
background-color: #cd201f;
}

.icon-item:nth-child(3) .icon-link i::after{
background-color: #55acee;
}



.icon-item:nth-child(4) .icon-link i::after{
background-color: #dd4b39;
}

2.設定hover之後,位置移動到原本icon的位置

1
2
3
4
5
6
7
/* 讓顏色回到原來的位置 */
.icon-link:hover i::after{
top: 0;
right: 0;
border-radius: 0;

}

3.讓圓形色彩隱藏

1
2
3
.icon-link i{
over-flow:hidden;
}

漢堡的動畫

  • line-1,line-2,line-3 位置改變的設定
  • 這裏使用js,增加change的class名稱

1
2
3
4
5
6
7
8
9
10
11
12
.change .line-1{
transform: rotateZ(-45deg);
}

.change .line-2{
transform: translate(5px,20px);
}

.change .line-3{
transform: rotateZ(45deg);
}

1
2
3
document.querySelector('.hamburger-menu').addEventListener('click', () => {
document.querySelector('.nav-wrapper').classList.toggle('change')
})

resposive

  • 針對螢幕大小,來設定內容為的寬、高與字型大小

Day22:小事之 Media Query

響應式網站設計基本觀念(2):CSS媒體查詢(CSS Media Queries)


介紹

成品

  • 這是一個展現作品集的一頁式網頁
    • 頁面的排版主要使用grid執行
    • 網頁整的色調,練習:root設定
    • 練習聯絡欄的排版
  • 另外,有使用到一些些js的部分,如設定滾動的效果、點擊後畫面的變化,但因主要練習排版,所以筆記內容並未多加提及

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--===== HEADER =====-->
<header class="l-header">


<nav class="nav bd-grid">
<div>
<a href="#" class="nav__logo">Jhon Doe</a>
</div>
<div class="nav_manue" id="nav-menu">
<ul class="nav_list">
<li class="nav_item"><a href="#home" class="nav_link">Home</a></li>
<li class="nav_item"><a href="#abour" class="nav_link">About</a></li>
<li class="nav_item"><a href="#skills" class="nav_link">Skills</a></li>
<li class="nav_item"><a href="#portfolio" class="nav_link">Portfolio</a></li>
<li class="nav_item"><a href="#contact" class="nav_link">Contact</a></li>

</ul>

</div>
<div class="nav__toggle" id="nav-toggle">
<i class='bx bx-menu'></i>
</div>
</nav>

</header>

header的建構

css 變數

1
2
3
4
5
6
7
8
9
/*建立全域變數*/
:root {
--csscoke-red: #f00;
}

/*套用變數*/
.section-item {
color: var( --csscoke-red );
}

csscoke
:root中使用關鍵符號 –建立了一個 CSS 變數,並且給予該變數名稱叫做 csscoke-red ,然後給予這個變數名稱一個值 #f00,這表示後面要套用這個變數名稱的項目,會直接取得這個 #f00

參考資料::root 根目錄選取器 - 叫你阿爸出來講

grid-template-columns

1
2
3
4
5
6
7
8
9
.bd-grid{
max-width: 1024px;
display: grid;
grid-template-columns: 100%;
grid-column-gap: 2rem;
width: calc(100% - 2rem);
margin-left: var(--mb-2);
margin-right: var(--mb-2);
}

卡伯斯
grid-template-columns 定義水平方向的空間,grid-template-rows 定義垂直方向的空間
.wrap { grid-template-columns: repeat(2, 1fr 2fr) 100px; /* grid-template-columns: repeat({次數}, {格線...} | {格線...}) | {格線...}; */ }
fr 這個單位,這個單位能夠將可用的 剩餘空間 做比例分割,以上面的 1fr 2fr 為例,空間將被分割成 1/3、2/3 兩個大小。
另一個是 repeat,可以重複隔線。

CSS Grid 屬性介紹
一行 CSS 程式碼搞定響應式佈局
CSS沒有極限 - CSS的神奇Calc運算

home

1
2
3
4
5
6
7
8
9
10
11
12
.home__scroll{
align-self: flex-end;
padding-bottom: var(--mb-4);
}

/* 直行旋轉 */

.home__scroll-link{
writing-mode: vertical-lr;
transform: rotate(-180deg);
color: var(--white-color);
}

skills

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--===== SKILLS =====-->
<section class="skills section" id="skills">
<h2 class="section-title">Skills</h2>

<div class="skills__container bd-grid">
<div class="skills__box">
<h3 class="skills__subtitle">Development</h3>
<span class="skills__name">Html</span>
<span class="skills__name">Css</span>
<span class="skills__name">Javascript</span>
<span class="skills__name">Scss</span>
<span class="skills__name">React</span>
<span class="skills__name">Vue</span>

<h3 class="skills__subtitle">Design</h3>
<span class="skills__name">Figma</span>
<span class="skills__name">Adobe XD</span>
<span class="skills__name">Photoshop</span>
</div>

<div class="skills__img">
<img src="./img/skill.jpg" alt="">
</div>
</div>
</section>

.skills__container{ row-gap: 2rem; } 使欄位2rem的空格

rem 也是相對的文字尺寸,和 em 使用方法接近,不同的是他僅相對於 root 層級的文字大小(網頁中的 html)。
如何更愉快地使用rem —— 別說你懂CSS相對單位
實際展示 EM 與 REM 的差異

1
2
3
4
5
6
7
8
9
.skills__name{
display: inline-block;
font-size: var(--small-font-size);
margin-right: var(--mb-2);
margin-bottom: var(--mb-3);
padding: .25rem .5rem;
background-color: var(--white-color);
border-radius: .25rem;
}
  • 中間的技能名稱設定

contact

  • 輸入框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* name,email */
.contact__inputs{
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: 1rem;
}

/* 文字輸入框 */

.contact__input{
width: 100%;
padding: .8rem;
outline: none;
border: 1.5px solid var(--dark-color);
font-size: var(--normal-font-size);
margin-bottom: var(--mb-4);
border-radius: .5rem;
}
  • 按鈕
1
2
3
4
5
6
7
8
9
10
11
12
13
14

.contact__button{
display: block;
background-color: var(--first-color);
color: var(--white-color);
padding: .75rem 2.5rem;
/* 若用margin-right:auto<會靠左邊 */
margin-left: auto;
border-radius: .5rem;
border: none;
outline: none;
font-size: var(--normal-font-size);
cursor: pointer;
}

footer


參考資料:

1. z-index

CSS position 、 z-index 筆記│鼠年全馬鐵人挑戰 #13
合理使用z-index数值

2. 滾動

點擊連結之後,自動滾動到適當的位置

[CSS scroll-behavior和JS scrollIntoView讓頁面滾動平滑](https://www.itread01.com/fyehkp.html

3. icon

4. flex

圖解 Flexbox 基本屬性

練習來源:

youtube:Responsive Personal Portfolio Website HTML CSS And JAVASCRIPT | Mobile First