學習筆記

Es6變量聲明的方式
Let聲明變量
{1.是塊級變量聲明的關鍵字,所聲明的變量只在所在的代碼塊有效,
2.動態賦值。例let a;a=100;
3.let聲明的變量名不可以再用。例
function func() {
let a = 10;
var a = 1;
}
// 報錯
function func() {
let a = 10;
let a = 1;
}
}

For{for循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。
例子:
for (let i = 0; i < 3; i++) {
let i = ‘abc’;
console.log(i);
}
// abc
// abc
// abc
}
Var聲明變量
{命令會發生“變量提升”現象,即變量可以在聲明之前使用,值爲undefined
例子:
console.log(foo); // 輸出undefined
var foo = 2;
變量bar用let命令聲明,不會發生變量提升。這表示在聲明它之前,變量bar是不存在的,這時如果用到它,就會拋出一個錯誤。
例子:
console.log(bar); // 報錯ReferenceError
let bar = 2;
}
塊級作用域域函數聲明:{
ES5 規定,函數只能在頂層作用域和函數作用域之中聲明,不能在塊(即{}包含的部分)級作用域聲明。
ES6 引入了塊級作用域,明確允許在塊級作用域之中聲明函數。ES6 規定,塊級作用域之中,函數聲明語句的行爲類似於let,在塊級作用域之外不可引用。(瀏覽器環境可能不遵循這樣的規則)
}
Const聲明變量
{1.const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
2.變量的聲明和初始化必須同時進行。
3.塊級作用域有效
4. const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至於它指向的數據結構是不是可變的,就完全不能控制了。
例子:
const foo = {};
// 爲 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop // 123
// 將 foo 指向另一個對象,就會報錯
foo = {}; // TypeError: “foo” is read-only
}
頂層對象的屬性
頂層對象,在瀏覽器環境指的是window對象,在 Node 指的是global對象。ES5 之中,頂層對象的屬性與全局變量是等價的。
window.a = 1;
a // 1

a = 2;
window.a // 2
上面代碼中,頂層對象的屬性賦值與全局變量的賦值,是同一件事。
頂層對象的屬性與全局變量掛鉤,被認爲是 JavaScript 語言最大的設計敗筆之一。這樣的設計帶來了幾個很大的問題,首先是沒法在編譯時就報出變量未聲明的錯誤,只有運行時才能知道(因爲全局變量可能是頂層對象的屬性創造的,而屬性的創造是動態的);其次,程序員很容易不知不覺地就創建了全局變量(比如打字出錯);最後,頂層對象的屬性是到處可以讀寫的,這非常不利於模塊化編程。另一方面,window對象有實體含義,指的是瀏覽器的窗口對象,頂層對象是一個有實體含義的對象,也是不合適的。
ES6 爲了改變這一點,一方面規定,爲了保持兼容性,var命令和function命令聲明的全局變量,依舊是頂層對象的屬性;另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬於頂層對象的屬性。也就是說,從 ES6 開始,全局變量將逐步與頂層對象的屬性脫鉤。
var a = 1;
// 如果在 Node 的 REPL 環境,可以寫成 global.a
// 或者採用通用方法,寫成 this.a
window.a // 1

let b = 1;
window.b // undefined
上面代碼中,全局變量a由var命令聲明,所以它是頂層對象的屬性;全局變量b由let命令聲明,所以它不是頂層對象的屬性,返回undefined。
globalThis 對象
JavaScript 語言存在一個頂層對象,它提供全局環境(即全局作用域),所有代碼都是在這個環境中運行。但是,頂層對象在各種實現裏面是不統一的。

Es6解構賦值
{
1.賦值運算符“=”左右的模式相同(都是數組,或者都是可遍歷的對象)。如果等號的右邊不是數組(或者嚴格地說,不是可遍歷的結構,參見《Iterator》一章),那麼將會報錯。事實上,只要某種數據結構具有 Iterator 接口,都可以採用數組形式的解構賦值。
2.數組結構賦值
2.1可以設定默認值,沒有對應的值就用默認值代替。例子
let [foo = true] = [];
foo // true
let [x, y = ‘b’] = [‘a’]; // x=‘a’, y=‘b’
let [x, y = ‘b’] = [‘a’, undefined]; // x=‘a’, y=‘b’
2.2默認值可以引用解構賦值的其他變量,但該變量必須已經聲明。
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined
上面最後一個表達式之所以會報錯,是因爲x用y做默認值時,y還沒有聲明。
}
3.對象的結構賦值
{
1帶被賦值的對象中有屬性名,根據屬性名相同給變量賦值,如1.3;沒有屬性名,就根據變量名和屬性名相同賦值,如1.1。
例子:
1.1let { bar(變量名), foo } = { foo(屬性名): ‘aaa’, bar: ‘bbb’ };
foo // “aaa”
bar // “bbb”
1.2let { baz } = { foo: ‘aaa’, bar: ‘bbb’ };
baz // undefined
解構失敗,變量的值等於undefined。
1.3注意:let {foo(匹配模式): baz(實際變量的變量名) } = { foo: ‘aaa’, bar: ‘bbb’ };
baz // “aaa”
2對象的解構也可以指定默認值,默認值生效的條件是,對象的屬性值嚴格等於undefined(即等號左邊的值嚴格是unefined)
例子:var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null

}

Es6對字符串的擴展

  1. 對Unicode編碼的支持(更多細節參見教材)
  2. ES6 爲字符串添加了遍歷器接口(詳見《Iterator》一章),使得字符串可以被for…of循環遍歷。
  3. For …of 的用法
    例子:for (let codePoint(存儲變量) of ‘foo’(待遍歷的字符串)) {
    console.log(codePoint)
    }
    // “f”
    // “o”
    // “o”
  4. 模板字符串
    4.1模板字符串(template string)是增強版的字符串,用反引號()標識。它可以當作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量。模板字符串中嵌入變量,需要將變量名寫在${}之中。大括號內部可以放入任意的 JavaScript 表達式,最終表達式的值都將轉化爲字符串。 4.2模板字符串可以跟在函數名後作其參數,例子: alert123// 等同於 alert(123) 在模板字符串轉化爲函數參數的過程中,非變量部分合並做爲函數的第一個參數;每個變量按順序依次作爲後續的參數。 例子: let a = 5; let b = 10; tagHello ${ a + b } world ${ a * b }`;
    // 等同於
    tag(['Hello ', ’ world ', ‘’], 15, 50);

Es6 對函數的擴展
1.ES6 允許爲函數的參數設置默認值,即直接寫在參數定義的後面。函數的參數不先聲明,直接用合法的標識符。
function log(x, y = ‘World’) {
console.log(x, y);
}

log(‘Hello’) // Hello World
log(‘Hello’, ‘China’) // Hello China
log(‘Hello’, ‘’) // Hello
2.在函數體中不能聲明和參數變量同名的變量的
function foo(x = 5) {
let x = 1; // error
const x = 2; // error
}
3使用參數默認值時,函數不能有同名參數。
例子:
// 不報錯
function foo(x, x, y) {
// …
}
// 報錯
function foo(x, x, y = 1) {
// …
}
// SyntaxError: Duplicate parameter name not allowed in this context
4 參數儘量不要省略 傳入undefined,將觸發該參數等於默認值,null則沒有這個效果。
有默認值的參數不是尾參數時,不可以只省略他而不省略他後面的參數。例子:
function f(x, y = 5, z) {
return [x, y, z];
}

f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 報錯
f(1, undefined, 2) // [1, 5, 2]
5.函數的length屬性只計算第一個給默認值以前的參數個數。
例子:
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
6.有默認值參數的作用域
一旦設置了參數的默認值,函數進行聲明初始化時,參數會形成一個單獨的作用域(context)。等到初始化結束,這個作用域就會消失。這種語法行爲,在不設置參數默認值時,是不會出現的。(我的理解:默認值中有賦值表達式,付給參數變量的值(即等號的右邊)首先在這個單獨的作用域尋找值,沒有的話再從上層作用域尋值)
var x = 1
function f(x, y = x) {
console.log(y);
}
f(2) // 2

let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
------------------------------------------------------------------------------如果此時,全局變量x不存在,就會報錯。
function f(y = x) {
let x = 2;
console.log(y);
}

f() // ReferenceError: x is not defined

Es6
函數的rest參數
Rest參數爲一個數組,形式爲(…變量名)
rest 參數之後不能再有其他參數(即只能是最後一個參數),否則會報錯。
// 報錯
function f(a, …b, c) {
// …
}
函數的length屬性,不包括 rest 參數。
(function(a) {}).length // 1
(function(…a) {}).length // 0
(function(a, …b) {}).length // 1

箭頭函數

Iterator
它是一種接口,爲各種不同的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就可以完成遍歷操作(即依次處理該數據結構的所有成員)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章