摘要:和命令命令在聲明所在的塊級作用域內有效。解構賦值從數組和對象中提取值,對變量進行賦值,這被稱為解構。數值和布爾值的解構解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。默認值解構賦值允許指定默認值。
let和const命令 let命令
在聲明所在的塊級作用域內有效。
只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。
在同一個作用域內,不允許重復聲明變量。var可以重復聲明。
let命令不存在變量提升。var命令會發生”變量提升“現象。因此使用let命令聲明的變量,凡是在聲明之前就使用這些變量,就會報錯。
塊級作用域與函數聲明在塊級作用域之中聲明的函數,在塊級作用域之外不可引用。
在瀏覽器的 ES6 環境中,塊級作用域內聲明的函數,行為類似于var聲明的變量。
ES6 的塊級作用域允許聲明函數的規則,只在使用大括號的情況下成立,如果沒有使用大括號,就會報錯。
應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。
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標準入門》這本書有300頁左右,除了幾個新的API和js語法的擴展,真正有價值的內容并不多。所謂存在即合理,每部分的...
摘要:但是有了尾調用優化之后,遞歸函數的性能有了提升。常被用來檢查對象中是否存在某個鍵名,集合常被用來獲取已存的信息。循環解構對象本身不支持迭代,但是我們可以自己添加一個生成器,返回一個,的迭代器,然后使用循環解構和。 一、let和const 在JavaScript中咱們以前主要用關鍵var來定義變量,ES6之后,新增了定義變量的兩個關鍵字,分別是let和const。對于變量來說,在ES5中...
閱讀 3418·2021-11-25 09:43
閱讀 2301·2021-09-06 15:02
閱讀 3546·2021-08-18 10:21
閱讀 3345·2019-08-30 15:55
閱讀 2352·2019-08-29 17:06
閱讀 3539·2019-08-29 16:59
閱讀 968·2019-08-29 13:47
閱讀 2765·2019-08-26 13:24