看自己本地環境的node js
版本 node --version
master node --version
v14.6.0
不同的javascript引擎,語法跑出來的結果不太相同
不同的js版本,LTS (長期支援 Long-term support)可能不一樣
Production applications should only use Active LTS or Maintenance LTS releases
y = `test` // string interpolation
let x = 10; // 第一次出現時宣告
// 三種字串宣告方式:單引號、雙引號、反引號
let y = '100';
let a = "";
// grave, backtick 這個在js和其他程式語言的功能不一樣
let b = `test`;
let z = x + y;
console.log(z);
let userName = "John";
let greeting = "Hello, " + userName + ", how are you?";
// string interpolation
let greeting2 = `Hello, ${userName}, Nice to meet you. how are you?`;
console.log(greeting)
console.log(greeting2)
以前版本的javascript
只有:
ruby 還有 block scope
def foo
x = 100
end
puts x # 會出錯
# hello-ruby.rb:5:in `<main>': undefined local variable or method `x' for main:Object (NameError)
拿到x的方法
def foo
x = 100
puts x
end
foo() # 100
scope的概念
def foo
x = 100
puts x
end
x = 1000
puts x # 1000
let 放在function內(會出錯)
function foo() {
let x1 = 100;
// ReferenceError: x1 is not defined at Object.<anonymous> (/Users/tingtinghsu/Documents/projects/astro_js/Day1/hello-foo.js:6:13)
}
foo();
console.log(x1);
let x1 = 100;
function foo() {
//let x1 = 100;
}
foo();
console.log(x1); //=> 100
如果放在function內但不宣告 => 變成全域變數
function foo() {
x1 = 100;
}
foo();
console.log(x1); //=> 100
行為良好的程式語言是否該取得i
?
for (var i = 0; i < 10; i++) {
}
console.log(i); // => 會印出10
為了不要讓i
被取得,使用let
(超過可以使用的範圍再取用時就會噴錯)
for (let i = 0; i < 10; i++) {
}
console.log(i);
ReferenceError: i is not defined
at Object.<anonymous> (/Users/tingtinghsu/Documents/projects/astro_js/Day1/for.js:4:13)
let是新的語法
(rails webpacker: 拿到js的新語法,翻譯成大部分瀏覽器可以使用的舊語法)
比起var
,用let
的好處
function bar(x) {
for (var j = 0; j < x; j++) {
// 1. 拿得到 j
}
// 2. 拿得到 j
}
// 3. 拿不到 j
function bar(x) {
for (let j = 0; j < x; j++) {
// 1. 拿得到 j
}
// 2. 拿不到 j
}
// 3. 拿不到 j
var userName1 = "Johnny Doe"
console.log(userName1); // Johnny Doe
兩句交換,後為什麼會印出undefined
?
console.log(userName);
var userName = "John Doe" // undefined
console.log(userName);
var userName = "John Doe" //
//javascript直譯器跑完檔案時,會把上面那句話拆成兩層,
//然後`var userName`會被提升到檔案最上層
var userName
userName = "John Doe"
回傳值return
和console.log
的區別
function greeting(name) {
// say a friendly hi
console.log("Hello world! This is" + name) // 印出Hello world! This istai
return `name: ${name}` //回傳 name: tai
}
let ret = greeting('tai')
console.log(ret);
跟ruby
的語法不同,如果沒有return
,就不會有回傳值
function greeting1(name) {
console.log("Hello world! This is" + name)`
}
let result = greeting1("Mary")
console.log(result) // undefined
ruby
def bar(x)
if(x < 100) {
return 100
} else {
300 # return 300
}
end
呼叫函式call
, invoke
時一定要加括弧 foo()
function greeting2(name) {
// say a friendly hi
console.log("Hello world! This is" + name)
console.log("function ends") // 偵測到無法執行的程式碼
return // 自以為有分號,結果變成沒有回傳值
`name: ${name}`
}
let result2 = greeting2("Mary")
console.log(result2) // undefined
Ruby: 如果一個function隸屬於一個物件,就是一個method
依照ruby的method規則,以下會出錯
p [1, 2, 3, 4, 5, 6].map def i
i + 1
end
但是在JS裡,函式是自由的
以下是沒有名字的函式
let res8 = [1, 2, 3, 4, 5].map(function(i){ return i + 1})
console.log(res8) #=> [ 2, 3, 4, 5, 6 ]
把函式提出來 (JS函式的good part)
function add1(i){ return i + 1}
let res8 = [1, 2, 3, 4, 5].map(add1)
console.log(res8)
==
與 ===
==
會自動幫忙轉型
比較時,盡量使用嚴格比較===
let numberOne = 1
let stringOne = "1"
console.log(numberOne == stringOne) // true console.log(numberOne === stringOne) // false
(桃紅色的區域會發生很多奇怪的事!)
計算車資
let cartTotal = 1000;
let ratio;
function getRatio(total) {
if(total > 1000) {
return 0.8;
} else if (total > 500) {
return 0.9;
} else {
return 1;
}
}
console.log(cartTotal * getRatio(cartTotal))
let array = [1, 2, 3, 4, 5, 6];
let res50 = [0, 0, ...array, 7, 8, 9]
res50[0] = 100;
// 彈性,瑣碎:開頭可以調整,跳的走也可以 eg i +=2
for(var i = 0; i < res50.length; i ++) {
let result = res50[i] + 1;
console.log('I got a number: ', result) // => I got a number: 101
}
console.log(i) // => 印出11, 最後的檢查會再做一次,但是發現條件不會符合
console
I got a number: 101
I got a number: 1
I got a number: 2
I got a number: 3
I got a number: 4
I got a number: 5
I got a number: 6
I got a number: 7
I got a number: 8
I got a number: 9
I got a number: 10
11
像ruby版本寫法的迴圈
for(let x of res50){
console.log(x) // 走的過程不會去亂動陣列本身
}
let gender = 'F', title;
switch(gender) {
case 'M':
title = 'Mr.';
break;
case 'F':
title = 'Ms.';
break;
default:
title = '';
}
console.log(title);
[]
let array = [1, 2, 3, 4, 5, 6];
let res2 = array;
console.log(res2); // => [ 1, 2, 3, 4, 5, 6 ]
let res5 = array.pop();
console.log(res5); // => 6
let res8 = array.slice(1,4);
console.log(res8); // => [2, 3, 4]
// immutible: 不可被修改的
// push pop slice 這些函式會動到陣列本身
// functional派:不要動到array本身
let res12 = [...array, 7 ,8 ,9]
console.log(res12); // => [[ 1, 2, 3, 4, 5, 7, 8, 9]
{}
:鍵值對:像是字典的東西在JavaScript叫做Object
Object的兩種用法:
let areaCode = { // 查表
'us': '01',
'tw': '886',
'hk': '86',
}
let student = { // 表達物件狀態
'name': 'John',
'age': 18,
'gender': 'M',
'favorite': ['music', 'eat'],
}
let areaCode = {
'us': '01',
'tw': '886',
'hk': '86'
}
let country = 'hk'
console.log(areaCode[country]) // => 86
取值與設值的規則:
如果是為了拿到特定的結果,使用[]
,其他時候用.
let areaCode = {
'us': '01',
'tw': '886',
'hk': '86'
}
let student = {
'name': 'John',
'age': 18,
'gender': 'M',
'favorite': ['music', 'eat']
}
let country = 'hk'
console.log(areaCode[country]) //=> 為了取出`86`這個值
console.log(student.age)
function baz(x){
let amount, total, qty; //先寫出來放著
//do something
amount = 100;
}
用function baz(x)
這種方式定義function
把不重要的小函式藏在底下
baz(1000)
function baz(x){
var amount, total, qty;
//do something
amount = 100;
console.log(amount + x)
}
putInPot('beef') // beef in pot
function putInPot(x) {
console.log(`${x} in pot`)
}
// function指定給變數
let lalala = function (x) {
console.log(`${x} in pot`)
}
let addOne = function(x) {return x + 1}
let addOne2 = x => x + 1 // 前面是參數,後面是回傳值
// 第一步:把function拿掉
let addOne = (x) => {
return x + 1
}
// 第二步:把{}和return拿掉
let addOne = (x) => x + 1
// 第三步:如果參數只有一個,()可以拿掉
let addOne = x => x + 1
如果參數有兩個,不能走第三步(不能把括弧拿掉)
let addOne = (x, y) => x + y + 1
處理函式的函式
原始的寫法長這樣:
putInPot('beef');
putInPot('water');
console.log('I make dinner with beef')
boomboom('chicken')
boomboom('coconut');
console.log('I make dinner with chicken')
function putInPot(x) {
console.log(`${x} in pot`)
}
function boomboom(x) {
console.log(`cooking ${x}`)
}
beef in pot
water in pot
I make dinner with beef
cooking chicken
cooking coconut
I make dinner with chicken
把pattern找出來
// cook('第一個食材'、'第二個食材','callback function': 這邊人家會透過參數丟一個函式進來,自己決定什麼時候要呼叫
cook('beef', 'water', putInPot);
cook('chicken', 'coconut', boomboom);
// 高階函式:處理函式的函式
function cook(i1, i2, f) {
f(i1)
f(i2)
console.log(`I make dinner with ${i1}`)
}
cook('beef',
'water',
x => console.log(`${x} in pot`))
cook('beef',
'water',
x => console.log(`cooking ${x}`))
// 函數是自由的,console log也是一個function,所以可以提到外面來
let pp = console.log
cook('beef',
'water',
x => pp(`${x} in pot`))
cook('beef',
'water',
x => pp(`cooking ${x}`))
下堂課前情提要:
用函式產生函式:呼叫高階函式的時候,直接把函式定義在後面
[1, 2, 3, 4, 5].map(x => x + 1)
[1, 2, 3, 4, 5].select(x => x > 3)
[1, 2, 3, 4, 5].reduce(x, acc => x + acc)
let curriedAdd = x => y => z => x + y + z
eg. 雖然不知道什麼時候會發生,但某個事件觸發的時候,會呼叫後面的函式
<body>
<button id="btn">Don't Click</button>
<script>
document
.querySelector('#btn')
.addEventListener('click', () => {
for (let i = 0; i < 5; i++) {
alert('Hey!!!! WTF')
}
alert('OK..')
})
</script>
</body>