第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

ES6-10 入門教程

Symbol

1. 前言

在 ES5 中基礎(chǔ)數(shù)據(jù)類型有 5 種:BooleanNull、Undefined、Number、String,ES6 新增了一個(gè)基礎(chǔ)數(shù)據(jù)類型 Symbol 符號(hào)、代號(hào)的意思,它是獨(dú)一無二的,也就是說使用它聲明的變量是獨(dú)一無二的。引入這個(gè)數(shù)據(jù)類型有什么作用呢?

我們知道在 ES5 中, 對(duì)象的屬性名都是字符串,容易造成屬性名沖突。比如,你使用了一個(gè)他人提供的對(duì)象,但又想為這個(gè)對(duì)象添加新的方法(mixin 模式),新方法的名字就有可能與現(xiàn)有方法產(chǎn)生沖突,ES6 引入 Symbol 就可以解決這個(gè)問題。不僅如此 Symbol 的使用還有很多,在元編程中也發(fā)揮很大的作用。下面我們就來看看 Symbol 的 使用。

2. 語法詳解

2.1 基本語法

使用 Symbol() 會(huì)返回一個(gè)獨(dú)一無二的變量,可以作為對(duì)象的 key 存在,返回的值是 symbol 類型,該類型具有靜態(tài)屬性和靜態(tài)方法。

Symbol([description])
參數(shù) 描述
description (可選)是字符串類型,對(duì) symbol 的描述

2.2 基本語法

Symbol() 是一個(gè)方法,返回的值是 symbol 類型,使用如下:

var s1 = Symbol();
var s2 = Symbol();
console.log(s1 === s2)  // false
console.log(typeof s1)	// symbol

上面的代碼中,使用 Symbol 聲明的變量 s1 和 s2,雖然它們看上去是同一個(gè) Symbol 定義的,但其實(shí)是不相等的。

2.3 帶描述的 Symbol

Symbol 中可以傳入一些參數(shù),來描述定義的 Symbol 類型的值。

var s1 = Symbol('imooc');
var s2 = Symbol('imooc');
console.log(s1)         // Symbol(imooc)
console.log(s1 === s2)  // false

let s = Symbol({name: 'imooc'});
console.log(s);         // Symbol([object Object])

上面的代碼中,Symbol 接收的參數(shù)是一個(gè)對(duì) Symbol 的描述,即使兩個(gè) Symbol 接收相同值,兩個(gè)值也是不一樣的。另外,如果傳入的描述符是對(duì)象類型,內(nèi)部會(huì)將描述的內(nèi)容進(jìn)行 toString 操作,所以返回的結(jié)果是 [object Object]。

3. 作為對(duì)象的 key

Symbol 經(jīng)常會(huì)作為對(duì)象的屬性存在,如果這個(gè)屬性是用 symbol 來聲明的,則不可枚舉,也不能用 for...in、for...of 迭代。

對(duì)象上的 key,可以用取值表達(dá)式 (中括號(hào)) 的方式取出來,作為對(duì)象上的屬性,如下:

var s = Symbol('imooc');
var obj = {
  [s]: 1
}
obj     // {Symbol(imooc): 1}
obj[s]  // 1

上面的代碼,使用 Symbol 聲明了一個(gè)變量,然后作為對(duì)象的 key 給它賦值。取值的時(shí)候只能使用中括號(hào)的方式,因?yàn)檫@里的 s 是變量不能使用點(diǎn)的方式。下面是對(duì) obj 對(duì)象用 for...in 進(jìn)行的遍歷。

for(let key in obj) {
  console.log(obj[key])
}
// undefined

上面的代碼對(duì) obj 對(duì)象進(jìn)行迭代,但是沒有打印出對(duì)應(yīng)的值,說明用 Symbol 來聲明的屬性是不可枚舉的。如果想要獲取到這個(gè)屬性可以使用 Object.getOwnPropertySymbols(obj) 獲取。使用 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 也是不能返回想要的結(jié)果。

Object.getOwnPropertySymbols(obj);   // [Symbol(imooc)]
Object.keys(obj);                    // []
Object.getOwnPropertyNames(obj);     // []
JSON.stringify(obj);                 // "{}"

從上面的代碼中可以看到使用 Object.getOwnPropertySymbols() 可以獲取對(duì)象上所有 Symbol 類型的屬性,并返回一個(gè)數(shù)組。

另外,可以通過 description 方法獲取 Symbol 類型描述。

var s = Symbol('imooc');
s.description;    // "imooc"

4. Symbol.for () 和 Symbol.keyFor ()

Symbol.for(key) 方法也是聲明變量使用,不同的是 Symbol.for(key) 是在全局作用域下聲明的。它會(huì)根據(jù)給定的鍵 key 從運(yùn)行時(shí)的 symbol 注冊(cè)表中找到對(duì)應(yīng)的 symbol。如果找到了,則返回它。否則,新建一個(gè)與該鍵關(guān)聯(lián)的 symbol,并放入全局的 symbol 注冊(cè)表中,如果有已經(jīng)聲明了的 symbol 則不回重復(fù)聲明。

let s1 = Symbol.for('imooc');  
let s2 = Symbol.for('imooc');
function fn() {
  return Symbol.for('imooc');
}
console.log(s1, s2)       // Symbol(imooc) Symbol(imooc)
console.log(s1 === s2)    // true
console.log(fn() === s1)    // true

上面的代碼中可以看出來,使用 Symbol.for(key) 無論在哪里進(jìn)行聲明,都不會(huì)影響它們的值。

Symbol.keyFor() 通過 key 值獲取 symbol 的描述:

let s1 = Symbol.for('imooc');  
console.log(Symbol.keyFor(s1))  // imooc

5 實(shí)戰(zhàn)案例

5.1 解決屬性重名

在現(xiàn)實(shí)中姓名重復(fù)是很常見的,但是在 JavaScript 對(duì)象中,屬性名是唯一的存在。如果定義一個(gè)對(duì)象中有重復(fù)的屬性則會(huì)被覆蓋,這個(gè)現(xiàn)象叫做 “引用消除”。我們看下面的例子:

var person = {
  Tom: {sex: '男', age: 18},
  David: {sex: '男', age: 17},
  David: {sex: '女', age: 16},
}
console.log(person); // {Tom: {sex: "男", age: 18}, David: {sex: "女", age: 16}}

可以看到我們定義了一個(gè) person 對(duì)象,第一個(gè) David 對(duì)象被后一個(gè) David 引用消除了,所以只有第二個(gè) David 的數(shù)據(jù)。如果要解決這個(gè)問題可以使用 Symbol 來實(shí)現(xiàn)

var person = {
  Tom: {sex: '男', age: 18},
  [Symbol('David')]: {sex: '男', age: 17},
  [Symbol('David')]: {sex: '女', age: 16},
}
console.log(person) 
// {Tom: {sex: "男", age: 18}, Symbol(David): {sex: "男", age: 17}, Symbol(David): {sex: "女", age: 16}}

這樣就可以解決屬性名沖突的問題,需要注意的是使用這樣的方式定義對(duì)象數(shù)據(jù)存在一個(gè)問題,就是使用 for...in 或者使用 Object.keys() 遍歷時(shí) Symbol 屬性的數(shù)據(jù)不會(huì)被遍歷到,上文有具體說明。所以,如果想要遍歷到對(duì)象的值可以通過 Reflect.ownKeys() 去獲取對(duì)象的 key,然后進(jìn)行循環(huán)操作。

for (let key of Reflect.ownKeys(person)) {
	console.log(person[key])
}
// {sex: "男", age: 18}
// {sex: "男", age: 17}
// {sex: "女", age: 16}

5.2 消除魔術(shù)字符串

魔術(shù)字符串 指的是在代碼中多次出現(xiàn)與代碼形成強(qiáng)耦合的某一個(gè)具體的字符串或者數(shù)值,看下面的例子:

function getArea(shape, options) {
  let area = 0;

  switch (shape) {
   	case 'Circle':
      area = 3.14 * Math.pow(options.radius, 2)
      break;
    case 'Square':
      area = options.width * options.height;
      break;
  }
  return area;
}

getArea('Circle', { radius: 10 });		// 314
getArea('Square', { width: 10, height: 10 });	 // 100

上面的代碼中 ‘Circle’ 和 ‘Triangle’ 就屬于魔術(shù)字符串,常見的消除魔術(shù)字符串的方法就是使用變量替代,如下:

const shapeType = {
  circle: 'Circle',
  triangle: 'Square'
}
function getArea(shape, options) {
  let area = 0;

  switch (shape) {
   	case shapeType.circle:
      area = 3.14 * Math.pow(options.radius, 2)
      break;
    case shapeType.square:
      area = options.width * options.height;
      break;
  }
  return area;
}

getArea(shapeType.circle, { radius: 10 });		// 314
getArea(shapeType.square, { width: 10, height: 10 });	 // 100

上面的代碼中就消除了代碼的強(qiáng)耦合,其實(shí)我們不關(guān)注 shapeType 屬性的值,只要他們不同即可,有了 Symbol 這時(shí)我們就可以使用 Symbol 進(jìn)行描述,如下更改:

const shapeType = {
  circle: Symbol('Circle'),
  triangle: Symbol('Square')
}

6. 小結(jié)

本節(jié)學(xué)習(xí)了 ES6 新增數(shù)據(jù)類型 Symbol,使用它可以聲明一個(gè)獨(dú)一無二的變量,通常會(huì)作為對(duì)象的屬性存在,解決屬性名沖突的問題。注意這個(gè)屬性是不能被迭代的,如果想要迭代它可以使用 Reflect.ownKeys() 的方式去獲取 key 值。最后介紹了 Symbol 在實(shí)戰(zhàn)中的應(yīng)用。