亚洲成A人片在线观看网站_成年网站免费视频A在线双飞_日日日日做夜夜夜夜无码_久久夜色撩人精品国产小说

JavaScript 備忘清單

包含最重要概念、函數、方法等的 JavaScript 備忘單。 初學者的完整快速參考。

入門

介紹

JavaScript 是一種輕量級的解釋型編程語言。

打印調試

// => Hello world!
console.log('Hello world!');
// => Hello QuickReference
console.warn('hello %s', 'QuickReference');
// 將錯誤消息打印到 stderr
console.error(new Error('Oops!'));

斷點調試

function potentiallyBuggyCode() {
  debugger;
  // 做可能有問題的東西來檢查,逐步通過等。
}

debugger 語句調用任何可用的調試功能。

數字

let amount = 6;
let price = 4.99;
let home = 1e2;
let num = 1_000_000; // 位數過多可以用 _ 分割
let m = 0644;   // 八進制數字 420

let 關鍵字

let count; 
console.log(count); // => undefined
count = 10;
console.log(count); // => 10

const 關鍵字

const numberOfColumns = 4;
// TypeError: Assignment to constant...
numberOfColumns = 8;

變量

let x = null;
let name = "Tammy";
const found = false;
// => Tammy, false, null
console.log(name, found, x);
var a;
console.log(a); // => undefined

字符串

let single = 'Wheres my bandit hat?';
let double = "Wheres my bandit hat?";
// => 21
console.log(single.length);

算術運算符

5 + 5 = 10     // 加法 Addition
10 - 5 = 5     // 減法 Subtraction
5 * 10 = 50    // 乘法 Multiplication
10 / 5 = 2     // 除法 Division
10 % 5 = 0     // 取模 Modulo

注釋

// 此行將表示注釋
/* 
多行配置
部署前必須更改
以下配置。
*/

賦值運算符

let number = 100;
// 兩個語句都會加 10
number = number + 10;
number += 10;
console.log(number); 
// => 120

字符串插值

let age = 7;
// 字符串拼接
'Tommy is ' + age + ' years old.';
// 字符串插值
`Tommy is ${age} years old.`;

字符串

var abc = "abcdefghijklmnopqrstuvwxyz";
var esc = 'I don\'t \n know';    // \n 換行
var len = abc.length;            // 字符串長度
abc.indexOf("lmno");             // 查找子字符串,如果不包含則 -1
abc.lastIndexOf("lmno");         // 最后一次出現
abc.slice(3, 6);                 // 去掉“def”,負值從后面計算
abc.replace("abc","123");        // 查找和替換,接受正則表達式
abc.toUpperCase();               // 轉換為大寫
abc.toLowerCase();               // 轉換為小寫
abc.concat(" ", str2);           // abc + " " + str2
abc.charAt(2);                   // 索引處的字符:“c”
abc[2];                          // 不安全,abc[2] = "C" 不起作用
// 索引處的字符代碼:“c”-> 99
abc.charCodeAt(2);
// 用逗號分割字符串給出一個數組
abc.split(",");
// 分割字符
abc.split("");
// 匹配開頭字符串,如果忽略第二個參數,則從索引 0 開始匹配
abc.startsWith("bc", 1);
// 匹配結尾的字符串,如果忽略第二個參數,則默認是原字符串長度
abc.endsWith("wxy", abc.length - 1);
// padEnd 和 padStart 都用于填充長度,默認填充對象是空格
"200".padEnd(5); // "200  "
"200".padEnd(5, "."); // "200.."
// 重復字符
"abc".repeat(2); // "abcabc"
// trim、trimEnd 和 trimStart 用于去除首尾空格
" ab c ".trim(); // "ab c"
// 數字轉為十六進制 (16)、八進制 (8) 或二進制 (2)
(128).toString(16);

數字

var pi = 3.141;
pi.toFixed(0);    // 返回 3             
pi.toFixed(2);    // 返回 3.14 - 使用金錢
pi.toPrecision(2) // 返回 3.1
pi.valueOf();     // 返回號碼
Number(true);     // 轉換為數字
// 自 1970 年以來的毫秒數
Number(new Date())          
// 返回第一個數字:3
parseInt("3 months");       
// 返回 3.5
parseFloat("3.5 days");     
// 最大可能的 JS 數
Number.MAX_VALUE            
// 最小可能的 JS 編號
Number.MIN_VALUE            
// -無窮
Number.NEGATIVE_INFINITY    
// 無窮
Number.POSITIVE_INFINITY    

Math

const pi = Math.PI; // 3.141592653589793
Math.round(4.4); // = 4 - 數字四舍五入
Math.round(4.5); // = 5
Math.pow(2,8);   // = 256 - 2 的 8 次方    
Math.sqrt(49);   // = 7 - 平方根
Math.abs(-3.14); // = 3.14 - 絕對,正值
Math.ceil(3.14); // = 4 - 返回 >= 最小整數
// = 3 - 返回 <= 最大整數
Math.floor(3.99);       
// = 0 - 正弦
Math.sin(0);            
// OTHERS: tan,atan,asin,acos,余弦值
Math.cos(Math.PI);      
// = -2 - 最低值
Math.min(0, 3, -2, 2);  
// = 3 - 最高值
Math.max(0, 3, -2, 2);  
// = 0 自然對數
Math.log(1);            
// = 2.7182pow(E,x) 自然對數的底數
Math.exp(1);            
// 0 到 1 之間的隨機數
Math.random();          
// 隨機整數,從 1
Math.floor(Math.random() * 5) + 1;  

全局函數

// 像腳本代碼一樣執行字符串
eval();                     
// 從數字返回字符串
String(23);                 
// 從數字返回字符串
(23).toString();            
// 從字符串返回數字
Number("23");               
// 解碼 URI。 結果:“my page.asp”
decodeURI(enc);             
// 編碼 URI。 結果:“my%20page.asp”
encodeURI(uri);             
// 解碼 URI 組件
decodeURIComponent(enc);    
// 對 URI 組件進行編碼
encodeURIComponent(uri);    
// 是一個有限的合法數
isFinite();                 
// 是一個非法數字
isNaN();                    
// 返回字符串的浮點數
parseFloat();               
// 解析一個字符串并返回一個整數
parseInt();                 

JavaScript 條件

操作符

true || false;       // true
10 > 5 || 10 > 20;   // true
false || false;      // false
10 > 100 || 10 > 20; // false

邏輯運算符 &&

true && true;        // true
1 > 2 && 2 > 1;      // false
true && false;       // false
4 === 4 && 3 > 1;    // true

比較運算符

1 > 3                 // false
3 > 1                 // true
250 >= 250            // true
1 === 1               // true
1 === 2               // false
1 === '1'             // false

邏輯運算符

let lateToWork = true;
let oppositeValue = !lateToWork;
// => false
console.log(oppositeValue); 

空值合并運算符 ??

null ?? 'I win';         //  'I win'
undefined ?? 'Me too';   //  'Me too'
false ?? 'I lose'        //  false
0 ?? 'I lose again'      //  0
'' ?? 'Damn it'          //  ''

if Statement (if 語句)

const isMailSent = true;
if (isMailSent) {
  console.log('Mail sent to recipient');
}

Ternary Operator (三元運算符)

var age = 1;

// => true
var status = (age >= 18) ? true : false;

else if

const size = 10;
if (size > 20) {
  console.log('Medium');
} else if (size > 4) {
  console.log('Small');
} else {
  console.log('Tiny');
}
// Print: Small

== vs ===

0 == false     // true
0 === false    // false, 不同類型
1 == "1"       // true,  自動類型轉換
1 === "1"      // false, 不同類型
null == undefined  // true
null === undefined // false
'0' == false       // true
'0' === false      // false

== 只檢查值,=== 檢查值和類型。

switch 語句

const food = 'salad';

switch (food) {
  case 'oyster': console.log('海的味道');
    break;
  case 'pizza': console.log('美味的餡餅');
    break;
  default:
    console.log('請您用餐');
}

switch 多 case - 單一操作

const food = 'salad';

switch (food) {
  case 'oyster':
  case 'pizza':
    console.log('美味的餡餅');
    break;
  default:
    console.log('請您用餐');
}

JavaScript Functions 函數

函數

// 定義函數:
function sum(num1, num2) {
  return num1 + num2;
}
// 調用函數:
sum(3, 6); // 9

匿名函數

// 命名函數
function rocketToMars() {
  return 'BOOM!';
}
// 匿名函數
const rocketToMars = function() {
  return 'BOOM!';
}

箭頭函數 (ES6)

有兩個參數

const sum = (param1, param2) => { 
  return param1 + param2; 
}; 
console.log(sum(2,5)); // => 7 

沒有參數

const printHello = () => { 
  console.log('hello'); 
}; 
printHello(); // => hello

只有一個參數

const checkWeight = weight => { 
  console.log(`Weight : ${weight}`); 
}; 
checkWeight(25); // => Weight : 25 

簡潔箭頭函數

const multiply = (a, b) => a * b; 
// => 60 
console.log(multiply(2, 30)); 

從 ES2015 開始提供

返回關鍵字

// 有 return
function sum(num1, num2) {
  return num1 + num2;
}
// 該函數不輸出總和
function sum(num1, num2) {
  num1 + num2;
}

調用函數

// 定義函數
function sum(num1, num2) {
  return num1 + num2;
}
// 調用函數
sum(2, 4); // 6

立即執行函數

//命名函數并立即執行一次
(function sum(num1, num2) {
  return num1 + num2;
})(2,4)//6

函數表達式

const dog = function() {
  return 'Woof!';
}

函數參數

// 參數是 name
function sayHello(name) {
  return `Hello, ${name}!`;
}

函數聲明

function add(num1, num2) {
  return num1 + num2;
}

JavaScript 范圍

范圍

function myFunction() {
  var pizzaName = "Margarita";
  // 這里的代碼可以使用 PizzaName
  
}
// ? PizzaName 不能在這里使用

{ } 塊內聲明的變量

{
  let x = 2;
}
// ? x 不能在這里使用

{
  var x = 2;
}
// ? x 能在這里使用
var x = 2;       // Global scope
let x = 2;       // Global scope
const x = 2;       // Global scope

ES6 引入了兩個重要的新 JavaScript 關鍵字:let 和 const。這兩個關鍵字在 JavaScript 中提供了塊作用域。

塊作用域變量

const isLoggedIn = true;
if (isLoggedIn == true) {
  const statusMessage = 'Logged in.';
}
// Uncaught ReferenceError...
// 未捕獲的引用錯誤...
console.log(statusMessage);

全局變量

// 全局聲明的變量
const color = 'blue';
function printColor() {
  console.log(color);
}

printColor(); // => blue

let vs var

for (let i = 0; i < 3; i++) {
  // 這是“let”的最大范圍
  // i 可以訪問 ??
}
// i 不能訪問 ?

for (var i = 0; i < 3; i++) {
  // i 可以訪問 ??
}
// i 可以訪問 ??

var 的范圍是最近的函數塊,而 let 的范圍是最近的封閉塊。

帶閉包的循環

// 打印三次,不是我們的意思。
for (var i = 0; i < 3; i++) {
  setTimeout(_ => console.log(i), 10);
}

// 按預期打印 0、1 和 2。
for (let j = 0; j < 3; j++) { 
  setTimeout(_ => console.log(j), 10);
}

變量使用 let 有自己的副本,變量有使用 var 的共享副本。

JavaScript Arrays

方法

:-:-
Array.from()類似數組對象創建一個新的
Array.isArray()值是否是一個 Array
Array.of()創建一個新數組示例
.at()返回值索引對應的元素
.concat()合并兩個或多個數組
.copyWithin()淺復制替換某個位置
.entries()新的 Array Iterator 對象
.every()是否能通過回調函數的測試
.fill()固定值填充一個數組中
.filter()返回過濾后的數組
.find()第一個元素的值
.findIndex()第一個元素的索引
.findLast()最后一個元素的值
.findLastIndex()最后一個元素的索引
.flat()扁平化嵌套數組
.flatMap()與 flat 相同
.forEach()升序循環執行
.includes()是否包含一個指定的值
.indexOf()找到給定元素的第一個索引
.join()數組鏈接成一個字符串
.keys()每個索引鍵
.lastIndexOf()給定元素的最后一個索引
.map()循環返回一個新數組
.pop()刪除最后一個元素
.push()元素添加到數組的末尾
.reduce()循環函數傳遞當前和上一個值
.reduceRight()類似 reduce 從右往左循環
.reverse()數組元素的位置顛倒
.shift()刪除第一個元素
.slice()提取元素
.some()至少有一個通過測試函數
.sort()元素進行排序
.splice()刪除替換添加元素
.toLocaleString()字符串表示數組中的元素
.toString()返回字符串
.unshift()元素添加到數組的開頭
.values()返回新的 ArrayIterator 對象

數組

const fruits = ["apple", "dew", "banana"];
// 不同的數據類型
const data = [1, 'chicken', false];

屬性 .length

const numbers = [1, 2, 3, 4];
numbers.length // 4

索引

// 訪問數組元素
const myArray = [100, 200, 300];
console.log(myArray[0]); // 100
console.log(myArray[1]); // 200

可變圖表

添加刪除開始結束
push??
pop??
unshift??
shift??

方法 .push()

// 添加單個元素:
const cart = ['apple', 'orange'];
cart.push('pear'); 
// 添加多個元素:
const numbers = [1, 2];
numbers.push(3, 4, 5);

將項目添加到末尾并返回新的數組長度。

方法 .pop()

const fruits = ["apple", "dew", "banana"];
const fruit = fruits.pop(); // 'banana'

console.log(fruits); // ["apple", "dew"]

末尾刪除一個項目并返回已刪除的項目。

方法 .shift()

const array1 = [1, 2, 3];
const firstElement = array1.shift();
console.log(array1); // 輸出: Array [2, 3]
console.log(firstElement); // 輸出: 1

從頭刪除一個項目并返回已刪除的項目。

方法 .some()

const array = [1, 2, 3, 4, 5];
// 檢查元素是否為偶數
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// 預期輸出: true

方法 .concat()

const numbers = [3, 2, 1]
const newFirstNumber = 4
    
// => [ 4, 3, 2, 1 ]
[newFirstNumber].concat(numbers)
    
// => [ 3, 2, 1, 4 ]
numbers.concat(newFirstNumber)

如果你想避免改變你的原始數組,你可以使用 concat。

方法 .splice()

const months = ['Jan', 'March'];
months.splice(1, 0, 'Feb');
// 在索引 1 處插入
console.log(months);
// 預期輸出: Array ["Jan", "Feb", "March"]

months.splice(2, 1, 'May');
// 替換索引 2 處的 1 個元素
console.log(months);
// 預期輸出: Array ["Jan", "Feb", "May"]

方法 .unshift()

let cats = ['Bob'];
// => ['Willy', 'Bob']
cats.unshift('Willy');
// => ['Puff', 'George', 'Willy', 'Bob']
cats.unshift('Puff', 'George');

將項目添加到開頭并返回新的數組長度。

方法 .filter()

const words = ['js', 'java', 'golang'];
const result = words.filter(word => {
  return  word.length > 3
});
console.log(result);
// 預期輸出: Array ["java", "golang"]

JavaScript 循環

While 循環

while (condition) {
  // 要執行的代碼塊
}
let i = 0;
while (i < 5) {        
  console.log(i);
  i++;
}

反向循環

const fruits = ["apple", "dew", "berry"];
for (let i = fruits.length - 1; i >= 0; i--) {
  console.log(`${i}. ${fruits[i]}`);
}
// => 2. berry
// => 1. dew
// => 0. apple

Do...While 語句

x = 0
i = 0
do {
  x = x + i;
  console.log(x)
  i++;
} while (i < 5);
// => 0 1 3 6 10

For 循環

for (let i = 0; i < 4; i += 1) {
  console.log(i);
};
// => 0, 1, 2, 3

遍歷數組

for (let i = 0; i < array.length; i++){
  console.log(array[i]);
}
// => 數組中的每一項

Break

for (let i = 0; i < 99; i += 1) {
  if (i > 5) break;
  console.log(i)
}
// => 0 1 2 3 4 5

Continue

for (i = 0; i < 10; i++) {
  if (i === 3) {
    continue;
  }
  text += "The number is " + i + "<br>";
}

嵌套循環

for (let i = 0; i < 2; i += 1) {
  for (let j = 0; j < 3; j += 1) {
    console.log(`${i}-${j}`);
  }
}

for...in 循環

const fruits = ["apple", "orange", "banana"];
for (let index in fruits) {
  console.log(index);
}
// => 0
// => 1
// => 2

label 語句

var num = 0;

outPoint:
for(var i = 0; i < 10; i++) {
  for(var j = 0; j < 10; j++) {
    if(i == 5 && j == 5) {
      continue outPoint;
    }
    num++;
  }
}

alert(num);  // 95

alert(num) 的值可以看出,continue outPoint; 語句的作用是跳出當前循環,并跳轉到 outPoint(標簽)下的 for 循環繼續執行。

for...of 循環

const fruits = ["apple", "orange", "banana"];
for (let fruit of fruits) {
  console.log(fruit);
}
// => apple
// => orange
// => banana

for await...of

async function* asyncGenerator() {
  var i = 0;
  while (i < 3) {
    yield i++;
  }
}

(async function() {
  for await (num of asyncGenerator()) {
    console.log(num);
  }
})();

// 0
// 1
// 2

可選的 for 表達式

var i = 0;

for (;;) {
  if (i > 3) break;
  console.log(i);
  i++;
}

JavaScript 迭代器(Iterators)

分配給變量的函數

let plusFive = (number) => {
  return number + 5;  
};
// f 被賦值為 plusFive
let f = plusFive;
plusFive(3); // 8
// 由于 f 具有函數值,因此可以調用它。
f(9); // 14

回調函數

const isEven = (n) => {
  return n % 2 == 0;
}
let printMsg = (evenFunc, num) => {
  const isNumEven = evenFunc(num);
  console.log(`${num} is an even number: ${isNumEven}.`)
}
// Pass in isEven as the callback function
printMsg(isEven, 4); 
// => The number 4 is an even number: True.

數組方法 .reduce()

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, curVal) => {  
  return accumulator + curVal;
});
console.log(sum); // 10

數組方法 .map()

const members = ["Taylor", "Donald", "Don", "Natasha", "Bobby"];
const announcements = members.map((member) => {
  return member + " joined the contest.";
});
console.log(announcements);

數組方法 .forEach()

const numbers = [28, 77, 45, 99, 27];
numbers.forEach(number => {  
  console.log(number);
}); 

數組方法 .filter()

const randomNumbers = [4, 11, 42, 14, 39];
const filteredArray = randomNumbers.filter(n => {  
  return n > 5;
});

JavaScript 對象(Objects)

訪問屬性

const apple = { 
  color: 'Green',
  price: { bulk: '$3/kg', smallQty: '$4/kg' }
};
console.log(apple.color);      // => Green
console.log(apple.price.bulk); // => $3/kg

命名屬性

// 無效鍵名示例
const trainSchedule = {
  // 由于單詞之間的空格而無效。
  platform num: 10, 
  // 表達式不能是鍵。
  40 - 10 + 2: 30,
  // 除非用引號括起來,否則 + 號無效。
  +compartment: 'C'
}

不存在的屬性

const classElection = {
  date: 'January 12'
};
console.log(classElection.place); // undefined

可變的

const student = {
  name: 'Sheldon',
  score: 100,
  grade: 'A',
}
console.log(student)
// { name: 'Sheldon', score: 100, grade: 'A' }
delete student.score
student.grade = 'F'
console.log(student)
// { name: 'Sheldon', grade: 'F' }
student = {}
// TypeError: TypeError:分配給常量變量。

賦值簡寫語法

const person = {
  name: 'Tom',
  age: '22',
};
const {name, age} = person;
console.log(name); // 'Tom'
console.log(age);  // '22'

刪除運算符

const person = {
  firstName: "Matilda",
  hobby: "knitting",
  goal: "learning JavaScript"
};
delete person.hobby; // 或 delete person['hobby'];
console.log(person);
/*
{
  firstName: "Matilda"
  goal: "learning JavaScript"
} */

對象作為參數

const origNum = 8;
const origObj = {color: 'blue'};
const changeItUp = (num, obj) => {
  num = 7;
  obj.color = 'red';
};
changeItUp(origNum, origObj);
// 將輸出 8,因為整數是按值傳遞的。
console.log(origNum);
// 由于傳遞了對象,將輸出“red”
// 通過引用,因此是可變的。
console.log(origObj.color);

工廠函數

// 一個接受 'name','age' 和 'breed' 的工廠函數,
//  參數返回一個自定義的 dog 對象。
const dogFactory = (name, age, breed) => {
  return {
    name: name,
    age: age,
    breed: breed,
    bark() {
      console.log('Woof!');  
    }
  };
};

速記對象創建

const activity = 'Surfing';
const beach = { activity };
console.log(beach); // { activity: 'Surfing' }

this 關鍵字

const cat = {
  name: 'Pipey',
  age: 8,
  whatName() {
    return this.name  
  }
};
console.log(cat.whatName()); // => Pipey

方法

const engine = {
  // 方法簡寫,有一個參數
  start(adverb) {
    console.log(`The engine starts up ${adverb}...`);
  },  
  // 不帶參數的匿名箭頭函數表達式
  sputter: () => {
    console.log('The engine sputters...');
  },
};
engine.start('noisily');
engine.sputter();

Getters 和 setters

const myCat = {
  _name: 'Dottie',
  get name() {
    return this._name;  
  },
  set name(newName) {
    this._name = newName;  
  }
};
// 引用調用 getter
console.log(myCat.name);
// 賦值調用 setter
myCat.name = 'Yankee';

Proxy

Proxy 對象用于創建一個對象的代理,從而實現基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數調用等)。

// 用于攔截對象的讀取屬性操作。
const handler = {
    get: function(obj, prop) {
        return prop in obj ? obj[prop] : 37;
    }
};

const p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;

console.log(p.a, p.b);      // 1, undefined
console.log('c' in p, p.c); // false, 37

語法

const p = new Proxy(target, handler)
  • target 要使用 Proxy 包裝的目標對象(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理)。
  • handler 一個通常以函數作為屬性的對象,各屬性中的函數分別定義了在執行各種操作時代理 p 的行為。

方法

:-:-
Proxy.revocable()創建一個可撤銷的Proxy對象

handler 對象的方法

:-:-
handler.getPrototypeOf()Object.getPrototypeOf 方法的捕捉器
handler.setPrototypeOf()Object.setPrototypeOf 方法的捕捉器
handler.isExtensible()Object.isExtensible 方法的捕捉器
handler.preventExtensions()Object.preventExtensions 方法的捕捉器
handler.getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor 方法的捕捉器
handler.defineProperty()Object.defineProperty 方法的捕捉器
handler.has()in 操作符的捕捉器
handler.get()屬性讀取操作的捕捉器
handler.set()屬性設置操作的捕捉器
handler.deleteProperty()delete 操作符的捕捉器
handler.ownKeys()Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器
handler.apply()函數調用操作的捕捉器
handler.construct()new 操作符的捕捉器

Reflect

Reflect 是一個內置的對象,它提供攔截 JavaScript 操作的方法。這些方法與proxy handlers (en-US)的方法相同。Reflect不是一個函數對象,因此它是不可構造的。

// 檢測一個對象是否存在特定屬性
const duck = {
  name: 'Maurice',
  color: 'white',
  greeting: function() {
    console.log(`Quaaaack! My name is ${this.name}`);
  }
}

Reflect.has(duck, 'color');
// true
Reflect.has(duck, 'haircut');
// false

靜態方法

:-:-
Reflect.apply(target, thisArgument, argumentsList)對一個函數進行調用操作,同時可以傳入一個數組作為調用參數。和 Function.prototype.apply() 功能類似
Reflect.construct(target, argumentsList[, newTarget])對構造函數進行 new 操作,相當于執行 new target(...args)
Reflect.defineProperty(target, propertyKey, attributes)和 Object.defineProperty() 類似。如果設置成功就會返回 true
Reflect.deleteProperty(target, propertyKey)作為函數的delete操作符,相當于執行 delete target[name]
Reflect.get(target, propertyKey[, receiver])獲取對象身上某個屬性的值,類似于 target[name]
Reflect.getOwnPropertyDescriptor(target, propertyKey)類似于 Object.getOwnPropertyDescriptor()。如果對象中存在該屬性,則返回對應的屬性描述符,否則返回 undefined
Reflect.getPrototypeOf(target)類似于 Object.getPrototypeOf()
Reflect.has(target, propertyKey)判斷一個對象是否存在某個屬性,和 in 運算符 的功能完全相同
Reflect.isExtensible(target)類似于 Object.isExtensible()
Reflect.ownKeys(target)返回一個包含所有自身屬性(不包含繼承屬性)的數組。(類似于 Object.keys(), 但不會受enumerable 影響)
Reflect.preventExtensions(target)類似于 Object.preventExtensions()。返回一個Boolean
Reflect.set(target, propertyKey, value[, receiver])將值分配給屬性的函數。返回一個Boolean,如果更新成功,則返回true
Reflect.setPrototypeOf(target, prototype)設置對象原型的函數。返回一個 Boolean,如果更新成功,則返回 true

JavaScript this 綁定

隱式綁定

function foo() {
  console.log(this)
}
let obj1 = {
  name: "obj1",
  foo: foo
}
let obj2 = {
  name: "obj2",
  obj1: obj1
}
obj2.obj1.foo() // [Object obj1]

隱式丟失

let a = obj2.obj1.foo()
a() // Window
  • 指定隱式綁定:必須在調用的對象內部有一個對函數的引用(比如一個屬性)
  • 將以上調用賦值給一個變量,結果最終會是 Window
  • 在 a 被調用的位置沒有進行過任何顯示綁定,最終全局對象 window 會調用它(Window.a

顯示綁定

function getName(a1, a2) {
  console.log("此人" + this.name, "歲數" + (a1 + a2))
}
let person = {
  name: "zhangsan"
}

call

call 第一個參數接受 this 作用域,剩余參數傳遞給其調用的函數

getName.call(person, 18, 12)

apply

apply 第一個參數與 call 相同,第二個參數是其調用函數的參數數組

getName.apply(person, [18, 12])

bind

bind 函數會返回一個新函數

getName.bind(person,18,12)()
//或者可以這樣
getName.bind(person)(18, 12)
//或者這樣
getName.bind(person).bind(null, 18)(12)

內置函數中的 this

數組中的一些方法,類似于 map、forEach 等,可以自己設置綁定 this

const obj = {
  name: "zhangsan"
}
const array = [1, 2, 3];
array.map(function(value){
  console.log(this.name)
}, obj)
// zhangsan x3 

其中一些全局對象,如 setTimeout 等,它們和未顯示綁定 this 的部分數組方法一樣,都會指向全局對象(Window

setTimeout(function(){ 
  console.log(this)
}, 1000) // Window

JavaScript Classes

靜態方法/字段

class Dog {
  constructor(name) {
    this._name = name;  
  }
  
  introduce() { 
    console.log('This is ' + this._name + ' !');  
  }
  
  // 靜態方法
  static bark() {
    console.log('Woof!');  
  }

  static {
    console.log('類靜態初始化塊調用');
  }
}

const myDog = new Dog('Buster');
myDog.introduce();

// 調用靜態方法
Dog.bark();

公有靜態字段

class ClassStaticField {
  static staticField = 'static field'
}

console.log(ClassStaticField.staticField)
// 預期輸出值:"static field"? 

Class

class Song {
  constructor() {
    this.title;
    this.author;
  }
  
  play() {
    console.log('Song playing!');
  }
}

const mySong = new Song();
mySong.play();

extends

// Parent class
class Media {
  constructor(info) {
    this.publishDate = info.publishDate;
    this.name = info.name;
  }
}
// Child class
class Song extends Media {
  constructor(songData) {
    super(songData);
    this.artist = songData.artist;
  }
}
const mySong = new Song({ 
  artist: 'Queen', 
  name: 'Bohemian Rhapsody', 
  publishDate: 1975
});

Class Constructor

class Song {
  constructor(title, artist) {
    this.title = title;
    this.artist = artist;
  }
}
const mySong = new Song('Bohemian Rhapsody', 'Queen');
console.log(mySong.title);

Class Methods

class Song {
  play() {
    console.log('Playing!');
  }
  
  stop() {
    console.log('Stopping!');
  }
}

JavaScript Modules

Export / Import

// myMath.js
// 默認導出 Default export
export default function add(x,y){
  return x + y
}
// 正常導出 Normal export
export function subtract(x,y){
  return x - y
}
// 多重導出 Multiple exports
function multiply(x,y){
  return x * y
}
function duplicate(x){
  return x * 2
}
export {
  multiply, duplicate
}

import 加載模塊

// main.js
import add, { subtract, multiply, duplicate } from './myMath.js';
console.log(add(6, 2));      // 8 
console.log(subtract(6, 2))  // 4
console.log(multiply(6, 2)); // 12
console.log(duplicate(5))    // 10
// index.html
<script type="module" src="main.js"></script>

Export Module

// myMath.js
function add(x,y){
  return x + y
}
function subtract(x,y){
  return x - y
}
function multiply(x,y){
  return x * y
}
function duplicate(x){
  return x * 2
}
// node.js 中的多個導出
module.exports = {
  add,
  subtract,
  multiply,
  duplicate
}

require 加載模塊

// main.js
const myMath = require('./myMath.js')
console.log(myMath.add(6, 2));      // 8 
console.log(myMath.subtract(6, 2))  // 4
console.log(myMath.multiply(6, 2)); // 12
console.log(myMath.duplicate(5))    // 10

JavaScript Promises

Promise

創建 promises

new Promise((resolve, reject) => {
  if (ok) {
    resolve(result)
  } else {
    reject(error)
  }
})

使用 promises

promise
  .then((result) => { ··· })
  .catch((error) => { ··· })

Promise 方法

Promise.all(···)
Promise.race(···)
Promise.reject(···)
Promise.resolve(···)

執行器函數

const executorFn = (resolve, reject) => {
  resolve('Resolved!');
};
const promise = new Promise(executorFn);

setTimeout()

const loginAlert = () => {
  console.log('Login');
};
setTimeout(loginAlert, 6000);

Promise 狀態

const promise = new Promise((resolve, reject) => {
  const res = true;
  // 一個異步操作。
  if (res) {
    resolve('Resolved!');
  }
  else {
    reject(Error('Error'));
  }
});
promise.then(
  (res) => console.log(res),
  (err) => console.error(err)
);

.then() 方法

const promise = new Promise((resolve, reject) => {    
  setTimeout(() => {
    resolve('Result');
  }, 200);
});

promise.then((res) => {
  console.log(res);
}, (err) => {
  console.error(err);
});

.catch() 方法

const promise = new Promise(
  (resolve, reject) => {  
  setTimeout(() => {
    reject(Error('Promise 無條件拒絕。'));
  }, 1000);
});

promise.then((res) => {
  console.log(value);
});

promise.catch((err) => {
  console.error(err);
});

Promise.all()

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3);
  }, 300);
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(2);
  }, 200);
});
Promise.all([promise1, promise2]).then((res) => {
  console.log(res[0]);
  console.log(res[1]);
});

鏈接多個 .then()

const promise = new Promise(
  resolve => 
    setTimeout(() => resolve('dAlan'),100)
);

promise.then(res => {
  return res === 'Alan' 
    ? Promise.resolve('Hey Alan!')
    : Promise.reject('Who are you?')
})
.then((res) => {
  console.log(res)
}, (err) => {
  console.error(err)
});

避免嵌套的 Promise 和 .then()

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => {
    resolve('*');
  }, 1000);
});
const twoStars = (star) => {  
  return (star + star);
};
const oneDot = (star) => {  
  return (star + '.');
};
const print = (val) => {
  console.log(val);
};
// 將它們鏈接在一起
promise.then(twoStars).then(oneDot).then(print);

JavaScript Async-Await

異步

function helloWorld() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Hello World!');
    }, 2000);
  });
}

// 異步函數表達式
const msg = async function() {
  const msg = await helloWorld();
  console.log('Message:', msg);
}

// 異步箭頭函數
const msg1 = async () => {
  const msg = await helloWorld();
  console.log('Message:', msg);
}

msg(); // Message: Hello World! <-- 2 秒后
msg1(); // Message: Hello World! <-- 2 秒后

解決 Promises

let pro1 = Promise.resolve(5);
let pro2 = 44;
let pro3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});
Promise.all([pro1, pro2, pro3]).then(function(values) {
  console.log(values);
});
// expected => Array [5, 44, "foo"]

異步等待 Promises

function helloWorld() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Hello World!');
    }, 2000);
  });
}
async function msg() {
  const msg = await helloWorld();
  console.log('Message:', msg);
}
msg(); // Message: Hello World! <-- 2 秒后

錯誤處理

// 數據不完整
let json = '{ "age": 30 }';

try {
  let user = JSON.parse(json); // <-- 沒有錯誤
  console.log( user.name );    // no name!
} catch (e) {
  console.error( "Invalid JSON data!" );
}

異步等待運算符

function helloWorld() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Hello World!');
    }, 2000);
  });
}
async function msg() {
  const msg = await helloWorld();
  console.log('Message:', msg);
}
msg(); // Message: Hello World! <-- 2 秒后

JavaScript 請求

JSON

const jsonObj = {
  "name": "Rick",
  "id": "11A",
  "level": 4  
};

另見:JSON 備忘單

XMLHttpRequest

const xhr = new XMLHttpRequest();
xhr.open('GET', 'mysite.com/getjson');

XMLHttpRequest 是一個瀏覽器級別的 API,它使客戶端能夠通過 JavaScript 編寫數據傳輸腳本,而不是 JavaScript 語言的一部分。

GET

const req = new XMLHttpRequest();
req.responseType = 'json';
req.open('GET', '/getdata?id=65');
req.onload = () => {
  console.log(xhr.response);
};
req.send();

POST

const data = { weight: '1.5 KG' };
const xhr = new XMLHttpRequest();
// 初始化一個請求。
xhr.open('POST', '/inventory/add');
// 一個用于定義響應類型的枚舉值
xhr.responseType = 'json';
// 發送請求以及數據。
xhr.send(JSON.stringify(data));
// 請求成功完成時觸發。
xhr.onload = () => {
  console.log(xhr.response);
}
// 當 request 遭遇錯誤時觸發。
xhr.onerror = () => {
  console.log(xhr.response);
}

fetch api

fetch(url, {
    method: 'POST',
    headers: {
      'Content-type': 'application/json',
      'apikey': apiKey
    },
    body: data
}).then(response => {
  if (response.ok) {
    return response.json();
  }
  throw new Error('Request failed!');
}, networkError => {
  console.log(networkError.message)
})

JSON 格式

fetch('url-that-returns-JSON')
  .then(response => response.json())
  .then(jsonResponse => {
    console.log(jsonResponse);
  });

promise url 參數獲取 API

fetch('url')
  .then(response  => {
    console.log(response);
  }, rejection => {
    console.error(rejection.message);
  });

Fetch API 函數

fetch('//api-xxx.com/endpoint', {
  method: 'POST',
  body: JSON.stringify({id: "200"})
}).then(response => {
  if(response.ok){
    return response.json();  
  }
  throw new Error('Request failed!');
}, networkError => {
  console.log(networkError.message);
}).then(jsonResponse => {
  console.log(jsonResponse);
})

async await 語法

const getSuggestions = async () => {
  const wordQuery = inputField.value;
  const endpoint = `${url}${queryParams}${wordQuery}`;
  try{
    const response = await fetch(endpoint, {cache: 'no-cache'});
    if(response.ok){
      const jsonResponse = await response.json()
    }
  }
  catch(error){
    console.log(error)
  }
}