国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ES6學習筆記1--let和const命令、解構賦值和Symbol

liaosilzu2007 / 1373人閱讀

摘要:和命令命令在聲明所在的塊級作用域內有效。解構賦值從數組和對象中提取值,對變量進行賦值,這被稱為解構。數值和布爾值的解構解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。默認值解構賦值允許指定默認值。

let和const命令 let命令

在聲明所在的塊級作用域內有效。

只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。

在同一個作用域內,不允許重復聲明變量。var可以重復聲明。

let命令不存在變量提升。var命令會發生”變量提升“現象。因此使用let命令聲明的變量,凡是在聲明之前就使用這些變量,就會報錯。

塊級作用域與函數聲明

在塊級作用域之中聲明的函數,在塊級作用域之外不可引用。

在瀏覽器的 ES6 環境中,塊級作用域內聲明的函數,行為類似于var聲明的變量。

ES6 的塊級作用域允許聲明函數的規則,只在使用大括號的情況下成立,如果沒有使用大括號,就會報錯。
應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。

const

const聲明的變量不得改變值。只聲明不賦值,就會報錯。

在聲明所在的塊級作用域內有效。

不存在變量提升。

在同一個作用域內,不允許重復聲明變量。

const實際上保證的,是變量指向的那個內存地址不得改動。因此:

對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。

對于復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針,const只能保證這個指針是固定的。

例如:

const foo = {};

// 為 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop // 123

// 將 foo 指向另一個對象,就會報錯。因為常量foo儲存的是一個地址,這個地址指向一個對象。不可變的只是這個地址,即不能把foo指向另一個地址,但對象本身是可變的,所以依然可以為其添加新屬性。
foo = {}; // TypeError: "foo" is read-only
頂層對象的屬性

var命令和function命令聲明的全局變量是頂層對象的屬性,即頂層對象的屬性與全局變量是等價的。

let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性。

解構賦值

從數組和對象中提取值,對變量進行賦值,這被稱為解構。解構賦值左邊定義了要從原變量中取出什么變量。解構賦值允許,等號左邊的模式之中,不放置任何變量名。

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉為對象。由于undefined和null無法轉為對象,所以對它們進行解構賦值,都會報錯。

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
數組解構

數組的元素是按次序排列的,變量的取值由它的位置決定。

let [a, b, c] = [1, 2, 3];//從數組中提取值,按照對應位置,對變量賦值

本質上,這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。如果解構不成功,變量的值就等于undefined。

不完全解構:等號左邊的模式,只匹配一部分的等號右邊的數組。

let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

只要某種數據結構具有 Iterator 接口,都可以采用數組形式的解構賦值。

對象解構

對象解構需變量與屬性同名,才能取到正確的值。

let { foo,bar } = { foo: "aaa", bar: "bbb" };
//是let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };的簡寫形式
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined

如果變量名與屬性名不一致,必須寫成下面這樣。

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined
//foo是匹配的模式,baz才是變量。真正被賦值的是變量baz,而不是模式foo。

以下語句中變量的聲明和賦值是一體的

let {foo} = {foo: 1};

let命令下面一行的圓括號是必須的,否則會報錯。因為解析器會將起首的大括號,理解成一個代碼塊,而不是賦值語句。

let foo;
({foo} = {foo: 1}); // 成功

通過解構可以無需聲明來賦值一個變量。

({a, b} = {a: 1, b: 2})
//等同于
var {a, b} = {a: 1, b: 2}

數組本質是特殊的對象,因此可以對數組進行對象屬性的解構。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;//方括號這種寫法,屬于“屬性名表達式”
first // 1
last // 3
字符串解構

字符串也可以解構賦值。這是因為此時,字符串被轉換成了一個類似數組的對象。

const [a, b, c, d, e] = "hello";
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

類似數組的對象都有一個length屬性,因此還可以對這個屬性解構賦值。

let {length : len} = "hello";
len // 5
數值和布爾值的解構

解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

//數值和布爾值的包裝對象都有toString屬性,因此變量s都能取到值.
函數參數的解構賦值

函數的參數也可以使用解構賦值。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

上面代碼中,函數add的參數表面上是一個數組,但在傳入參數的那一刻,數組參數就被解構成變量x和y。對于函數內部的代碼來說,它們能感受到的參數就是x和y。

默認值

解構賦值允許指定默認值。如果默認值是一個表達式,那么這個表達式是惰性求值的,即只有在用到的時候,才會求值。

let [x, y = "b"] = ["a"]; // x="a", y="b"

var {x, y = 5} = {x: 1};
x // 1
y // 5

ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。所以,如果一個數組成員或對象的屬性值不嚴格等于undefined,默認值是不會生效的

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null
//數組成員是null,默認值就不會生效,因為null不嚴格等于undefined。

var {x = 3} = {x: null};
x // null

函數參數的解構也可以使用默認值。以下兩種寫法不一樣。

function move({x = 0, y = 0} = {}) {
  return [x, y];
}
move({x: 3}); // [3, 0]
//為變量x和y指定默認值
function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}
move({x: 3}); // [3, undefined]
//為函數move的參數指定默認值
模式不能使用圓括號

只有賦值語句非模式部分,可以使用圓括號。

({ p: (d) } = {}); // 正確
let [(a)] = [1];//報錯   因為變量聲明語句中,不能帶有圓括號。
function f([(z)]) { return z; }// 報錯 因為函數參數也屬于變量聲明,因此不能帶有圓括號。


[(b)] = [3]; // 正確 因為模式是取數組的第一個成員,跟圓括號無關。
([a]) = [5]; //報錯 因為賦值語句中,不能將整個模式,或嵌套模式中的一層,放在圓括號之中。
Symbol

ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。Symbol值通過Symbol函數生成。對象的屬性名現在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的 Symbol 類型。凡是屬性名屬于 Symbol 類型,就都是獨一無二的,可以保證不會與其他屬性名產生沖突。

注意,Symbol函數前不能使用new命令,否則會報錯。這是因為 Symbol 值不是對象,所以也不能添加屬性。基本上,它是一種類似于字符串的數據類型。Symbol函數可以接受一個字符串作為參數,表示對 Symbol 實例的描述。如果 Symbol 的參數是一個對象,就會調用該對象的toString方法,將其轉為字符串,然后才生成一個 Symbol 值。

var s1 = Symbol("foo");
var s2 = Symbol("bar");

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"

注意,Symbol函數的參數只是表示對當前 Symbol 值的描述,因此相同參數的Symbol函數的返回值是不相等的

// 沒有參數的情況
var s1 = Symbol();
var s2 = Symbol();

s1 === s2 // false

// 有參數的情況
var s1 = Symbol("foo");
var s2 = Symbol("foo");

s1 === s2 // false

Symbol 值不能與其他類型的值進行運算,會報錯。但是,Symbol 值可以顯式轉為字符串或布爾值,但是不能轉為數值。

var sym = Symbol("My symbol");

"your symbol is " + sym
// TypeError: can"t convert symbol to string

String(sym) // "Symbol(My symbol)"
Boolean(sym) // true
Number(sym) // TypeError
作為屬性名的 Symbol

由于每一個 Symbol 值都是不相等的,因此用于對象的屬性名時,就能保證不會出現同名的屬性。

var mySymbol = Symbol();

// 第一種寫法
var a = {};
a[mySymbol] = "Hello!";

// 第二種寫法
var a = {
  [mySymbol]: "Hello!"
};

// 第三種寫法
var a = {};
Object.defineProperty(a, mySymbol, { value: "Hello!" });

// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"

使用 Symbol 值定義屬性時,Symbol 值必須放在方括號之中。該屬性仍是公開屬性。因此,Symbol 值作為對象屬性名時,不能用點運算符。

var mySymbol = Symbol();
var a = {};

a.mySymbol = "Hello!";
a[mySymbol] // undefined
a["mySymbol"] // "Hello!"

上面代碼中,因為點運算符后面總是字符串,所以不會讀取mySymbol作為標識名所指代的那個值,導致a的屬性名實際上是一個字符串,而不是一個 Symbol 值。

Symbol 類型還可以用于定義一組常量,保證其值得唯一。Symbol 作為屬性名,該屬性不會出現在for...in、for...of循環中,也不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。可使用Object.getOwnPropertySymbols方法獲取對象的所有 Symbol 屬性名。

Symbol.for(),Symbol.keyFor()

Symbol.for():會先檢查給定的key是否已經存在,如果不存在才會新建一個值,該值會被登記在全局環境中供搜索。
Symbol():沒有登記制度,因此每次調用都會返回一個不同的值。

Symbol.for("bar") === Symbol.for("bar")
// true

Symbol("bar") === Symbol("bar")
// false


var s1 = Symbol("foo");
var s2=Symbol.for("foo");
s1===s2 //false

Symbol.keyFor():返回一個已登記的 Symbol 類型值的key。

var s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

var s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined 變量s2屬于未登記的Symbol值,所以返回undefined。

Symbol.for為Symbol值登記的名字,是全局環境的,可以在不同的 iframe 或 service worker 中取到同一個值。

內置的Symbol值

Symbol.hasInstance:對象的Symbol.hasInstance屬性,指向一個內部方法。當其他對象使用instanceof運算符,判斷是否為該對象的實例時,會調用這個方法。

Symbol.isConcatSpreadable:對象的Symbol.isConcatSpreadable屬性等于一個布爾值,表示該對象使用Array.prototype.concat()時,是否可以展開。數組的默認行為是可以展開。類似數組的對象的默認行為是不可以展開。Symbol.isConcatSpreadable屬性等于true或undefined時,都是可以展開的。對于一個類來說,Symbol.isConcatSpreadable屬性必須寫成實例的屬性。

let arr1 = ["c", "d"];
["a", "b"].concat(arr1, "e") // ["a", "b", "c", "d", "e"]
arr1[Symbol.isConcatSpreadable] // undefined

let obj = {length: 2, 0: "c", 1: "d"};
["a", "b"].concat(obj, "e") // ["a", "b", obj, "e"]
obj[Symbol.isConcatSpreadable] = true;
["a", "b"].concat(obj, "e") // ["a", "b", "c", "d", "e"]

Symbol.species:對象的Symbol.species屬性,指向當前對象的構造函數。創造實例時,默認會調用這個方法,即使用這個屬性返回的函數當作構造函數,來創造新的實例對象。

Symbol.match:對象的Symbol.match屬性,指向一個函數。當執行str.match(myObject)時,如果該屬性存在,會調用它,返回該方法的返回值。

String.prototype.match(regexp)
// 等同于
regexp[Symbol.match](this)

Symbol.replace:對象的Symbol.replace屬性,指向一個方法,當該對象被String.prototype.replace方法調用時,會返回該方法的返回值。

String.prototype.replace(searchValue, replaceValue)
// 等同于
searchValue[Symbol.replace](this, replaceValue)

Symbol.search:對象的Symbol.search屬性,指向一個方法,當該對象被String.prototype.search方法調用時,會返回該方法的返回值。

String.prototype.search(regexp)
// 等同于
regexp[Symbol.search](this)

Symbol.split:對象的Symbol.split屬性,指向一個方法,當該對象被String.prototype.split方法調用時,會返回該方法的返回值。

String.prototype.split(separator, limit)
// 等同于
separator[Symbol.split](this, limit)

Symbol.iterator:對象的Symbol.iterator屬性,指向該對象的默認遍歷器方法。

Symbol.toPrimitive:對象的Symbol.toPrimitive屬性,指向一個方法。該對象被轉為原始類型的值時,會調用這個方法,返回該對象對應的原始類型值。

Symbol.toStringTag:對象的Symbol.toStringTag屬性,指向一個方法。在該對象上面調用Object.prototype.toString方法時,如果這個屬性存在,它的返回值會出現在toString方法返回的字符串之中,表示對象的類型。也就是說,這個屬性可以用來定制[object Object]或[object Array]中object后面的那個字符串。

Symbol.unscopables:對象的Symbol.unscopables屬性,指向一個對象。該對象指定了使用with關鍵字時,哪些屬性會被with環境排除。

參考自:ECMAScript 6 入門

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/83037.html

相關文章

  • ES6

    摘要:情況一情況二這兩種情況,根據的規定都是非法的。的作用域與命令相同只在聲明所在的塊級作用域內有效。因此,將一個對象聲明為常量必須非常小心。頂層對象的屬性與全局變量掛鉤,被認為時語言最大的設計敗筆之一。 這是ES6的入門篇教程的筆記,網址:鏈接描述,以下內容中粗體+斜體表示大標題,粗體是小標題,還有一些重點;斜體表示對于自身,還需要下功夫學習的內容。這里面有一些自己的見解,所以若是發現問題...

    AZmake 評論0 收藏0
  • ES6學習總結(1

    摘要:返回一個對象,遍歷對象自身和繼承的所有可枚舉屬性不含,與相同和在紅寶書中就已經提到過屬性,表示的是引用類型實例的一個內部指針,指向該實例的構造函數的原型對象。 半個月前就決定要將ES6的學習總結一遍,結果拖延癥一犯,半個月就過去了,現在補起來,慚愧慚愧。 阮一峰的《ES6標準入門》這本書有300頁左右,除了幾個新的API和js語法的擴展,真正有價值的內容并不多。所謂存在即合理,每部分的...

    happyfish 評論0 收藏0
  • es6 學習筆記

    摘要:塊級作用域只有全局作用域和函數作用域,沒有塊級作用域,這帶來了很多不合理的場景。如聲明變量的方法只有兩種聲明變量的方法命令一共有六種命令變量的解構賦值允許按照一定的模式,從數組和對象中提取,按照位置的對應關系對變量賦值,這被稱為解構。 塊級作用域 es5只有全局作用域和函數作用域,沒有塊級作用域,這帶來了很多不合理的場景。 第一種場景:內層變量可能會覆蓋外層變量 var test = ...

    李昌杰 評論0 收藏0
  • ES6(中)

    摘要:它用來比較兩個值是否嚴格相等,與嚴格比較運算符的行為基本一致。兩個對象的地址不一樣與嚴格比較運算符的不同之處只有兩個一是不等于,二是等于自身基本用法方法用于對象的合并,將源對象的所有可枚舉屬性,賦值到目標對象。 這是ES6的入門篇教程的筆記,網址:鏈接描述,以下內容中粗體+斜體表示大標題,粗體是小標題,還有一些重點;斜體表示對于自身,還需要下功夫學習的內容。這里面有一些自己的見解,所以...

    dreamGong 評論0 收藏0
  • 學習ES6筆記──工作中常用到的ES6語法

    摘要:但是有了尾調用優化之后,遞歸函數的性能有了提升。常被用來檢查對象中是否存在某個鍵名,集合常被用來獲取已存的信息。循環解構對象本身不支持迭代,但是我們可以自己添加一個生成器,返回一個,的迭代器,然后使用循環解構和。 一、let和const 在JavaScript中咱們以前主要用關鍵var來定義變量,ES6之后,新增了定義變量的兩個關鍵字,分別是let和const。對于變量來說,在ES5中...

    curried 評論0 收藏0

發表評論

0條評論

liaosilzu2007

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<