ES 6知識点整理Symbolの応用

12293 ワード

Symbolは、ES 6に導入された新しいデータタイプで、ユニークな値を表しています.オブジェクトに向かって、各オブジェクトに文字列タイプの属性があります.新しい方法の名前は既存の方法と競合する可能性があります.Symbolの導入は各属性の名前が唯一無二であることを保証し、属性名の衝突を根本から防ぐ.
ES 6以前のオブジェクト属性の命名方法
var obj = {
  name:'Joh',
  'my name': 'Johnny'
}
console.log(obj.name); // Joh
console.log(obj['my name']); // Johnny
Symbolを導入すると、変数は繰り返さなくなります.
let name1 = Symbol('name');
let name2 = Symbol('name');
console.log(name1 === name2); // false
Symbol関数を呼び出したが、返ってくるSymbolタイプのname 1とname 2は同じではないことがわかる.
Symbolタイプを文字列タイプに変換
let name1 = Symbol('name');
let name2 = Symbol('name');

console.log(name1.toString());// Symbol(name)
console.log(String(name2)); // Symbol(name)
Symbolタイプをオブジェクトに適用する属性
let getName = Symbol('name');
let obj = {
  [getName]() {
    return 'Joh';
  }
}
console.log(obj[getName]()); // Joh
Symbolタイプの属性は一定の隠蔽性を持っています.
let name = Symbol('name');
let obj = {
  age:22,
  [name]:'Joh'
};

console.log(Object.keys(obj)); //         Symbol [name]  

//   for-in         Symbol [name]  
for(var k in obj) {
  console.log(k);
}

//    Object.getOwnPropertyNames           Symbol [name]  
console.log(Object.getOwnPropertyNames(obj)); 

//    Object.getOwnPropertySymbols   
var key = Object.getOwnPropertySymbols(obj)[0];
console.log(obj[key]); // Joh
Symbolタイプを使用してオブジェクトの私有属性をシミュレートします.
Userモジュール
'use strict';
let getName = Symbol('getName');

module.exports = class User {
  [getName]() {
    return 'Joh';
  }

  print() {
    console.log(this[getName]());
  }
}
テストUserモジュール
'use strict';

const User = require('./User');
let user = new User();
user.print(); // Joh

let getName = Symbol('getName');
user[getName](); // getName is not defined   ,    Symbol               
Symbol.forとSymbol.keyForの応用
let name1 = Symbol.for('name');
let name2 = Symbol.for('name');
console.log(name1 === name2); // true
console.log(Symbol.keyFor(name1)); // name   :      
Symbol.forを使用してSymbolタイプの値を取得し、Symbol.keyForを使用して前の文字列を取得します.
行列の単一項目をfor-ofを使って逐次出力します.
let arr = ['a', 'b', 'c'];
for(let item of arr) {
  console.log(item); //      a b c
}
Symbol.iteratorディケンサを使用して、配列の単項を一つずつ返します.
let arr = ['a', 'b', 'c'];
var iterator = arr[Symbol.iterator]();
// next     done      
console.log(iterator.next()); // {value: "a", done: false}
console.log(iterator.next()); // {value: "b", done: false}
console.log(iterator.next()); // {value: "c", done: false}
console.log(iterator.next()); // {value: undefined, done: true}
console.log(iterator.next()); // {value: undefined, done: true}
プログラムの最適化:
let arr = ['a', 'b', 'c'];
var iterator = arr[Symbol.iterator]();
// next     done      
var next = iterator.next();
while(!next.done) {
  console.log(next);
  next = iterator.next();
};
Symbol.iteratorのオブジェクト指向アプリケーションの例1:
'use strict';

class UserGroup {
  constructor(users) {
    // json {joh:111,lili:1123}
    this.users = users;
  }

  [Symbol.iterator]() {
    let self = this;
    let i = 0;
    const names = Object.keys(this.users);
    const length = names.length;

    // iterator   ,       
    return {
      next() {
        let name = names[i++];
        let qq = self.users[name];
        return {value: {name, qq}, done: i > length}
      }
    }
  }
}

let group = new UserGroup({'Joh':'595959','Lili':'888116'});
for (let user of group) {
  console.log(user);
}

// { name: 'Joh', qq: '595959' }
// { name: 'Lili', qq: '888116' }
Symbol.iteratorのオブジェクト指向アプリケーションの例2:
'use strict';

var obj = {'Joh':'56999', 'Lili':'899888'};

obj[Symbol.iterator] = function() {
  let self = this;
  let i = 0;
  const names = Object.keys(this);
  const length = names.length;

  // iterator   ,       
  return {
    next() {
      let name = names[i++];
      let qq = self[name];
      return {value: {name, qq}, done: i > length}
    }
  }

}
for (let u of obj) console.log(u);
プログラム最適化後:
'use strict';

var obj = {'Joh':'56999', 'Lili':'899888'};

let iteratorFun = function () {
  let self = this;
  let i = 0;
  const names = Object.keys(this);
  const length = names.length;

  // iterator   ,       
  return {
    next() {
      let name = names[i++];
      let qq = self[name];
      return {value: {name, qq}, done: i > length}
    }
  }
}

obj[Symbol.iterator] = iteratorFun;

for (let u of obj) console.log(u);
Symbol.iteratorは疑似配列に適用されます.
'use strict';

var obj = {
  length:2,
  '0':'abc',
  '1':'ddd'
}

/*
// if this , err: obj is not iterable
for (let i of obj) {
  console.log(i);
}
*/

obj[Symbol.iterator] = [][Symbol.iterator]; // handle this first

// then
for (let i of obj) {
  console.log(i);
}
文字列はSymbol.iteratorインターフェースを実現しました.
'use strict';

console.log('Joh'[Symbol.iterator]); // [Function: [Symbol.iterator]]

for(let char of 'Lili') {
  console.log(char);
}
同様に、ES 6でset、map文字列でSymbol.iteratorインターフェースを実現できます.