📚 JavaScript 語法基礎
Variables
let
name; // undefinedlet
name = 'Jamie';- 盡量一行一個變數宣告,這是 best practice
Constant
const
interestRate = 0.2;- 如果不會改變,盡量用 const 而不是 let
Primitives/Value types
- number
- string
- boolean
- symbol
- undefined
- null
let name = "jamie"; // string
let age = 30; // number
let isApproved = false; // boolean
let firstName = undefined; // undefined
let lastName = null; // clear a variable
typeof age; // "number"
typeof firstName; // "undefined". undefined 既是 type 也是 value
typeof lastName; // "object"
Reference types
- object
- array
- function
// --- object
let person = {
// object
name: "jamei", // property
age: 30,
};
person.name = "john"; // dot notation
person["age"] = 20; // bracket notation
let selection = "name";
person[selection] = "Jenny";
//--- array is also a 'object' type 💡
let selectedColors = ["red", "blue"]; // array
selectedColors[2] = "green"; // length is dynamic
console.log(selectedColors[0]);
console.log(selectedColors.length);
Functions
// 1. performing a task
function greet(name, lastName) {
// name is the parameter
console.log("hello world " + name + " " + lastName);
}
greet("jamie"); // jamie is the argument, actual value is applied
// 2. calculating a value
function square(number) {
return number * number;
}
let number = square(2);
Operators
- arithmetic
- assignment
- comparison
- equality (
strict
&lose
equality) - ternary operator (
? a : b
) - logical operator (
&&
,||
,!
)- 以下在 logical operator,會自動轉為 Falsy (false)
- undefined
- null
- 0
- false
- ''
- NaN
- 以下在 logical operator,會自動轉為 Falsy (false)
- bit operator(
|
,&
)
// arithmetic operator
console.log(x % 2); // remainder
console.log(x ** y); // exp
console.log(++x); // increment (++)
console.log(y--); // decrement (--)
// assignment operator
let x = 10;
x++; // x = x + 1
x += 5; // x = x + 5
x *= 3; // x = x * 3
// comparison operator
let x = 1;
console.log(x > 0); // true
// equality
console.log(x === 1);
console.log(x !== 1);
// strict equality (same type + value)
console.log(1 === 1); // true
console.log("1" === 1); // false
// lose equality (don't care type, automatically convert type)
console.log(1 == "1"); // true
console.log(true == 1); // true
// ternary operator
let poins = 110;
let type = points > 100 ? "gold" : "silver";
// logical
console.log(true && true); // logical AND (&&)
let highIncome = true;
let goodCreditScore = true;
let eligibleForLoan = highIncome && goodCreditScore; // true
let eligibleForLoan = highIncome || goodCreditScore; // logical OR (||)
let applicationRefused = !eligibleForLoan; // Not (!)
// automatically convert operand ->
false || "jamie"; // 'jamie'
false || 1; // 1
// 以下在 logical operator,會自動轉為 Falsy (false)
// undefined
// null
// 0
// false
// ''
// NaN
// short-circult
let userColor = "red";
let defaultColor = "blue";
let currentColor = userColor || defaultColor; // can provide default value if user not select
// bit operator application
// Read, Write, Execute
// 00000100
// 00000010
// 00000001
const readPermission = 4;
const writePermission = 2;
const executePremission = 1;
let myPermission = 0;
myPermission =
myPermission | readPermission | writePermission | executePermission;
let message = myPermission & readPermission ? "yes" : "no"; // 可以用來判斷有無權限
Conditional statements
- if else
if (condition) {
// statement
} else if (anotherCondition) {
// statement
} else {
// statement
}
- switch case
// switch case (can be string, number or boolean)
let role;
switch (role) {
case "guest":
console.log("Guest User");
break; // need
case "moderator":
console.log("Moderator User");
break;
default:
console.log("Unknow Role");
}
Flow control
-
For
loopfor (let i = 0; i < 5; i++) { console.log("hello world"); }
-
While
Looplet i = 0; while (i < 5) { if (i % 2 !== 0) console.log(i); i++; }
-
Do-while Loop
: execute at least oncelet i = 0; do { if (i % 2 !== 0) console.log(i); i++; } while (i <= 5);
-
For-in
Loop: 用在 propertyconst person = { name = 'jamie', age: 30 }; for (let key in person) { console.log(key, person[key]); } const colors = ['red', 'blue', 'green']; for (let inex in colors) console.log(index, colors[index]);
-
For-of
Loop: 用在 arrayconst colors = ["red", "blue", "green"]; for (let color of colors) console.log(color);
-
break
andcontinue
let i = 0; while (i <= 10) { if (i == 5) break; if (i % 2 === 0) { i++; continue; // 盡量不要用 } conosle.log(i); i++; }
-
exercise
function max(a, b) return (a > b) ? a : b; function isLandscape(width, height) { return (width > height); } // Math.floor(1.3) // 12 points suspend function checkSpeed(speed) { const speedLimit = 70; const kmPerPoint = 5; if (speed < speedLimit + kmPerPoint) { console.log("ok"); } else { const points = Math.floor((speed - speedLimit) / knPerPoint); if (points >= 12 ) console.log("suspend"); else console.log('points: ', points); } } const array = [0, null, undefined, '', 2, 3]; function countTruthy(array) { let count = 0; for (let element of array) { if (element) count++; } return count; } const movie = { title: 'a', release: 2018, director: 'b' }; function showProperties(obj) { for (let attr in obj) if (Typeof obj[attr] === 'string') console.log(attr, obj[attr]); } showProperties(movie); function showStars(row) { for (let i = 1; i <= row; i++) { let output = ''; for (let j = 0; j < i; j++) output += '*'; console.log(output); } } showStars(5); function showPrimes(limit) { for (let i = 2; i <= limit; i++) { let isPrime = true; for (let f = 2; f < limit; f++) { if ((i % f) === 0) { isPrime = false; break; } } if (isPrime) console.log(i); } } showPrimes(20);
Object
- object literal
// object literal
const circle = {
radius: 1,
location: {
x: 1,
y: 1,
},
isVisible: true,
draw: function () {
console.log("draw");
},
};
circle.draw();
factory function
function createCircle(radius) {
return {
radius: radius,
draw: function () {
console.log("draw");
},
};
}
// modern
function createCircle(radius) {
return {
radius,
draw() {
console.log("draw");
},
};
}
const circle1 = createCircle(1);
console.log(circle1);
constructor function
// PASCAL notion
function Circle(radius) {
this.radius = radius;
this.draw = function () {
console.log("draw");
};
}
const circle = new Circle(1);
delete circle.color;
delete circle.draw;
primitives are copied by their value, objects are copied by their reference.
- enumerate properties
const circle = {
radius: 1,
draw() {
console.log("draw");
},
};
for (let key in circle) {
console.log(key);
}
// 🔥 circle is not iterable!!! ERROR
for (let prop of circle) {
// WRONG!!
console.log(prop);
}
for (let key of Object.keys(circle)) console.log(key);
for (let entry of Object.entries(circle)) console.log(entry);
if ("radius" in circle) console.log("yes");
- Clone Object (
Shallow Copy
)
const circle = {
radius: 1,
draw() {
console.log("draw");
},
};
// old clone syntax
const another = {};
for (let key in circle) another[key] = circle[key];
// new clone syntax
const another = Object.assign({}, circle);
// spread operator to shallow copy 🔥
const another = { ...circle };
Math
(MDN)
Math.random(); // 0~1
Math.round(1.9); // 2
Math.max(1, 2, 3, 4, 5); // 5
String
object
// string primitive
const message = "this is my first string"; // typeof string
message.split(" ");
// string object
const another = new String("hi"); // typeof object
- template literal
const another = `Hi ${name}, ${2 + 3},
Thank you`;
- date
const now = new Date();
const date1 = new Date("May 11 2018 09:00");
now.toISOString();
Array
- add element
const numbers = [3, 4];
// End
numbers.push(5, 6);
console.log(numbers); // 3,4,5,6
// beginning
numbers.unshift(1, 2); // 1,2,3,4
// middle
numbers.splice(2, 0, "a", "b");
- find element (primitive)
const numbers = [1, 2, 3, 1, 4];
numbers.indexOf("a"); // -1 not found!
numbers.indexOf(1); // 0
numbers.lastIndexOf(1); // 3
console.log(numbers.indexOf(1) !== -1);
console.log(numbers.includes(1)); // new syntax 🔥
- find element (object)
const courses = [
{ id: 1, name: "a" },
{ id: 2, name: "b" },
];
const course = courses.find(function (course) {
return course.name === "a"; // criteria
});
console.log(course);
const course2 = courses.findIndex(function (course) {
return course.name === "a"; // 0
});
console.log(course2);
- arrow function
- 當你要傳一個 function 進去當作 callback 時
const courses = [
{ id: 1, name: "a" },
{ id: 2, name: "b" },
];
const course = courses.find(function (course) {
return course.name === "a";
});
// 只有一行 return 時
const course2 = courses.find((course) => course.name == "a");
console.log(course2);
- remove elements
const numbers = [1, 2, 3, 4];
// end
// numbers.push();
const last = numbers.pop();
console.log(last); // 4
// beginning
//numbers.unshift();
const first = numbers.shift();
console.log(first); // 1
// middle
numbers.splice(2, 1);
console.log(numbers); // 1, 2, 4
- empty array
const numbers = [1, 2, 3, 4];
let another = numbers;
// solution 1 💡
numbers = [];
console.log(numbers);
// solution 2 💡
numbers.length = 0;
// solution 3
numbers.splice(0, numbers.length);
// solution 4
while (numbers.length > 0) numbers.pop();
- combine & slice
const first = [1, 2, 3];
const second = [4, 5, 6];
const combined = first.concat(second); // [1,2,3,4,5,6]
const slice = combined.slice(2, 4); // [3,4]
const slice = combined.slice(2); // [3,4,5,6]
const slice = combined.slice(); // [1,2,3,4,5,6]
- spread operator (ES6)🔥
const combined = [...first, ...second];
const combined = [...first, "a", ...second, "b"]; // [1,2,3,'a',4,5,6,'b']
const copy = [...combined]; // copy
- iterate array
const numbers = [1, 2, 3];
for (let number of numbers) console.log(number);
numbers.forEach(function (number) {
console.log(number);
});
numbers.forEach((number) => console.log(number)); // arrow version
numbers.forEach((number, index) => console.log(index, number)); // also index 🔥
- join array, split string
const numbers = [1, 2, 3];
const joined = numbers.join(","); // '1,2,3'
const message = "This is my first message";
const parts = message.split(" "); // ['This', 'is', ..];
- sort array
const numbers = [2, 3, 1];
numbers.sort(); // [1,2,3]
numbers.reverse(); // [3,2,1]
const Courses = [
{ id: 1, name: "Node.js" },
{ id: 2, name: "JavaScript" },
];
Courses.sort(function (a, b) {
// a < b => -1
// a > b => 1
// a == b => 0
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
if (nameA < nameB) return -1;
if (nameA > nameB) return 1;
return 0;
});
- testing elements
- every()
- some()
const numbers = [1, 2, 3];
// 只要一個失敗,就回傳 false
const allPositive = numbers.every(function (value) {
return value >= 0;
});
// 只要有一個成立就回傳 true
const atLeastOnePositive = number.some(function (value) {
return value >= 0;
});
- Filter array
const number = [1, -1, 2, 3];
const filtered = numbers.filter(function (value) {
// [1,2,3]
return value >= 0;
});
const filtered = numbers.filter((n) => n >= 0); // arrow
- mappin array
- map 跟 filter return array, 可以 chain
const number = [1, -1, 2, 3];
const filtered = numbers.filter((n) => n >= 0);
const items = filtered.map((n) => "<li>" + n + "</li>");
console.log(items);
const html = "<ul>" + items.join("") + "</ul>";
const items = filtered.map((n) => {
const obj = { value: n };
return obj;
});
const items = filtered.map((n) => ({ value: n })); // 這邊用 () 將 obj 包起來,不然會出錯
- reduce array
const numbers = [1, -1, 2, 3];
let sum = 0;
for (let n of numbers) sum += n;
console.log(sum);
// alternative
const sum = numbers.reduce((accumulator, currentValue) => {
return accumulator + currentValue;
}, 0);
// arrow
const sum = numbers.reduct(
(accumulator, currentValue) => accumulator + currentValue
);