重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,天天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的能夠加入winter的專欄學習【原文有winter的語音】,若有侵權請聯繫我,郵箱:kaimo313@foxmail.com。前端
在 JavaScript 標準中,把語句分紅了兩種:普通語句和聲明型語句。數組
語句塊就是一對大括號。異步
{
var x, y;
x = 10;
y = 20;
}
複製代碼
語句塊的意義和好處在於:讓咱們能夠把多行語句視爲同一行語句。async
// 語句塊會產生做用域
{
let x = 1;
}
console.log(x); // Uncaught ReferenceError: x is not defined
複製代碼
空語句就是一個獨立的分號,實際上沒什麼大用。函數
;
複製代碼
if(a < b)
console.log(a);
複製代碼
if 和 else 連寫成多分支條件學習
if(a < 10) {
//...
} else if(a < 20) {
//...
} else if(a < 30) {
//...
} else {
//...
}
複製代碼
switch(num) {
case 1:
console.log(1);
case 2:
console.log(2);
case 3:
console.log(3);
}
// num等於1,輸出:1 2 3
// num等於2,輸出:2 3
// num等於3,輸出:3
switch(num) {
case 1:
console.log(1);
break;
case 2:
console.log(2);
break;
case 3:
console.log(3);
break;
}
// num等於1,輸出:1
// num等於2,輸出:2
// num等於3,輸出:3
複製代碼
winter 的見解是:「 switch 已經徹底沒有必要使用了,應該用 if else 結構代替。」。ui
let a = 5;
while(a--) {
console.log("*");
}
// 輸出:* * * * *
複製代碼
let a = 6;
do {
console.log(a);
} while(a < 6)
// 6
複製代碼
for(i = 0; i < 6; i++)
console.log(i);
// 0 1 2 3 4 5
for(var i = 0; i < 6; i++)
console.log(i);
// 0 1 2 3 4 5
for(let i = 0; i < 6; i++)
console.log(i);
// 0 1 2 3 4 5
for(const i = 0; i < 6; i++)
console.log(i);
// 0 Uncaught TypeError: Assignment to constant variable.
var j = 0;
for(const i = 0; j < 6; j++)
console.log(i);
// 0 0 0 0 0 0
複製代碼
for in
循環枚舉對象的屬性,體現了屬性的enumerable
特徵。this
let o = { a: 10, b: 20}
Object.defineProperty(o, "c", {enumerable: false, value: 30})
for(let p in o)
console.log(p);
// 輸出:a b
// enumerable爲true,輸出:a b c
複製代碼
for of 循環是很是棒的語法特性
。背後的機制是iterator
機制。spa
一、用於數組debug
for(let e of [1, 2, 3, 4, 5])
console.log(e);
// 1 2 3 4 5
複製代碼
二、如何爲一個對象添加 iterator
。
let o = {
[Symbol.iterator]:() => ({
_value: 0,
next(){
if(this._value == 10)
return {
done: true
}
else return {
value: this._value++,
done: false
};
}
})
}
for(let e of o)
console.log(e);
// 0 1 2 3 4 5 6 7 8 9
複製代碼
三、使用 generator function
。
function* foo(){
yield 0;
yield 1;
yield 2;
yield 3;
}
for(let e of foo())
console.log(e);
// 0 1 2 3
複製代碼
四、JavaScript 還爲異步生成器函數配備了異步的 for of
function sleep(duration) {
return new Promise(function(resolve, reject) {
setTimeout(resolve,duration);
})
}
async function* foo(){
i = 0;
while(true) {
await sleep(1000);
yield i++;
}
}
for await(let e of foo())
console.log(e);
// 從0開始,每隔1s加1,輸出:0 1 2 3 4 5....
複製代碼
return 語句用於函數中,它終止函數的執行,而且指定函數的返回值。
function squre(x){
return x * x;
}
複製代碼
break 語句用於跳出循環語句或者 switch 語句,continue 語句用於結束本次循環並繼續循環。
for(let i = 0; i < 2; i++){
console.log(i)
if( i == 0){
break;
}
}
// 0
for(let i = 0; i < 2; i++){
console.log(i)
if( i == 0){
continue;
}
}
// 0 1
複製代碼
with 語句把對象的屬性在它內部的做用域內變成變量。
let o = {a:1, b:2}
with(o){
console.log(a, b);
}
// 1 2
複製代碼
try 語句和 throw 語句用於處理異常。try 語句用於捕獲異常,用 throw 拋出的異常。
try
部分用於標識捕獲異常的代碼段catch
部分則用於捕獲異常後作一些處理(catch結構
會建立一個局部的做用域,不能再聲明變量 e ,不然會出錯。)finally
語句通常用於釋放資源,它必定會被執行try {
throw new Error("error");
} catch(e) {
console.log(e);
} finally {
console.log("finally");
}
// Error: error at <anonymous>:2:1
// finally
複製代碼
debugger 語句的做用是
:通知調試器在此斷點。在沒有調試器掛載時,它不產生任何效果。
一、var 聲明語句是古典的 JavaScript 中聲明變量的方式。而如今,基本使用 let 和 const 。
二、若是仍然想要使用 var,winter建議:把它當作一種保障變量是局部
的邏輯,遵循如下三條規則:
// 下面這裏x聲明瞭兩次
function add(x,y) {
console.log(x + y);
}
function multiply(x,y) {
console.log(x * y);
}
var x = 1, y = 2;
add(x, y);
for(var x = 0; x < 2; x++)
multiply(x,y);
// 3
// 0
// 2
// 使用let改造,用代碼塊限制了第一個 x 的做用域,這樣就更難發生變量命名衝突引發的錯誤。
{
let x = 1, y = 2;
add(x, y);
}
for(let x = 0; x < 2; x++)
multiply(x);
複製代碼
const a = 2;
if(true){
const a = 1;
console.log(a);
}
console.log(a);
// 1 2
複製代碼
一、const 和 let 語句在重複聲明時會拋錯,這可以有效地避免變量名無心中衝突。
let a = 2
const a = 1;
// Uncaught SyntaxError: Identifier 'a' has already been declared
複製代碼
二、let 和 const 聲明仍是會被預處理。若是當前做用域內有聲明,就沒法訪問到外部的變量。
const a = 2;
if(true){
console.log(a); // 拋錯
const a = 1;
}
// Uncaught ReferenceError: Cannot access 'a' before initialization
if(true){
console.log(a);
var a = 1;
}
// undefined
// 上面的對比就說明 const 聲明仍然是有預處理機制的。
複製代碼
class
最基本的用法只須要class
關鍵字、名稱和一對大括號。
一、class
的聲明特徵跟 const
和 let
相似,都是做用於塊級做用域,預處理階段則會屏蔽外部變量。
const a = 2;
if(true){
console.log(a); // 拋錯
class a {
}
}
// Uncaught ReferenceError: Cannot access 'a' before initialization
複製代碼
二、class
內部,可使用 constructor
關鍵字來定義構造函數。
// 這個例子來自 MDN,它展現了構造函數、getter 和方法的定義。
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
}
複製代碼
函數聲明使用 function 關鍵字。
一、帶 * 的函數是 generator
。生成器函數能夠理解爲返回一個序列的函數,它的底層是 iterator
機制。
二、async
函數是能夠暫停執行,等待異步操做的函數,它的底層是 Promise
機制。
function foo(){
}
function* foo(){
yield 1;
yield 2;
yield 3;
}
async function foo(){
await sleep(3000);
}
async function* foo(){
await sleep(3000);
yield 1;
}
複製代碼
三、函數的參數,能夠只寫形參名,還能夠寫默認參數和指定多個參數
function foo(a = 1, ...other) {
console.log(a, other)
}
foo();
// 1 []
foo(3,4);
// 3 [4]
複製代碼
用的少的須要增強一下,對於底層的東西實在瞭解的太少。。。