es6 학습 노트 - symbolv1.0_byKL

14171 단어
es6 학습 노트 - symbolv1.0
기본적으로 내용 을 한 번 베 꼈 는데 그 이 유 를 모 르 는 경우 가 많 지만 인상 을 깊 게 한 셈 이다. 그리고 모든 코드 를 나 는 수 동 으로 실행 한 적 이 있다.
  • ES6 는 유일한 값 을 나타 내 는 새로운 원시 데이터 형식 Symbol 을 도입 했다.

  • 자 바스 크 립 트 언어의 일곱 번 째 데이터 형식 입 니 다. 여섯 번 째 는 Undefined, Null, 불 값 (Boolean), 문자열 (String), 수치 (Number), 대상 (Object) 입 니 다.ES5 의 대상 속성 명 은 모두 문자열 로 속성 명 이 충돌 하기 쉽다.예 를 들 어 다른 사람 이 제공 하 는 대상 을 사 용 했 지만 이 대상 에 게 새로운 방법 (mixin 모드) 을 추가 하려 면 새로운 방법의 이름 이 기 존 방법 과 충돌 할 수 있 습 니 다.충돌 을 막 기 위해 ES6 가 심 볼 을 도입 한 이유 다.
    Symbol 값 은 Symbol 함 수 를 통 해 생 성 됩 니 다.대상 의 속성 명 은 현재 두 가지 유형 이 있 을 수 있 으 며, 하 나 는 원래 있 던 문자열 이 고, 다른 하 나 는 새로 추 가 된 Symbol 형식 이다.속성 명 이 Symbol 유형 에 속 하 는 것 은 모두 유일무이한 것 으로 다른 속성 명 과 충돌 하지 않 을 것 을 보증 할 수 있 습 니 다.
    let s = Symbol();
    typeof s
    // "symbol"

    Symbol 함 수 는 하나의 문자열 을 매개 변수 로 받 아들 여 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 mySymbol = Symbol();
    
    //      
    var a = {};
    a[mySymbol] = 'Hello!';
    
    //      
    var a = {
    //               Symbol  
      [mySymbol]: 'Hello!'
    };
    
    //      
    var a = {};
    //Object.defineProperty(obj, prop(            ), descriptor(              ))
    Object.defineProperty(a, mySymbol, { value: 'Hello!' });
    
    //            
    a[mySymbol] // "Hello!"

    증강 대상 표기 법
    let s = Symbol();
    
    let obj = {//     
      [s]: function (arg) { ... }//    
    };
    
    obj[s](123);
    //--------------------------
    let obj = {
      //        
      [s](arg) { ... }
    };

    상수 와 배합 하여 사용 하 다
    상수 가 같 지 않 을 수 있 도록
    log.levels = {
      DEBUG: Symbol('debug'),//    
      INFO: Symbol('info'),
      WARN: Symbol('warn')
    };
    log(log.levels.DEBUG, 'debug message');
    log(log.levels.INFO, 'info message');
    
    //--------------------------
    const COLOR_RED    = Symbol(); //               
    const COLOR_GREEN  = Symbol();
    
    function getComplement(color) {
      switch (color) {
        case COLOR_RED:
          return COLOR_GREEN;
        case COLOR_GREEN:
          return COLOR_RED;
        default:
          throw new Error('Undefined color');
        }
    }
    

    인 스 턴 스: 마술 문자열 제거
    마술 문자열 은 코드 에 여러 번 나타 나 코드 와 강 한 결합 을 이 루 는 구체 적 인 문자열 이나 수 치 를 말한다.스타일 이 좋 은 코드 는 마술 문자열 을 최대한 없 애고 의미 가 뚜렷 한 변수 로 대체 해 야 합 니 다.
    function getArea(shape, options) {
      var area = 0;
    
      switch (shape) {
        case 'Triangle': //      
          area = .5 * options.width * options.height;
          break;
        /* ... more code ... */
      }
    
      return area;
    }
    
    getArea('Triangle', { width: 100, height: 100 }); //      

    이렇게
    var shapeType = {
      triangle: 'Triangle'//        
    };
    //        Symbol    
    const shapeType = {
      triangle: Symbol()
    };
    //-------------------------
    function getArea(shape, options) {
      var area = 0;
      switch (shape) {
        case shapeType.triangle:
          area = .5 * options.width * options.height;
          break;
      }
      return area;
    }
    
    getArea(shapeType.triangle, { width: 100, height: 100 });

    속성 이름 옮 겨 다 니 기
    Symbol 은 속성 명 으로서 이 속성 은 for... in, for... of 순환 에 나타 나 지 않 고 Object. keys (), Object. getOwnProperty Names (), JSON. stringify () 에 의 해 되 돌아 오지 않 습 니 다.그러나 이것 은 개인 속성 도 아 닙 니 다. Object. getOWn Property Symbols 방법 이 있 습 니 다. 지정 한 대상 의 모든 Symbol 속성 명 을 얻 을 수 있 습 니 다.
    Object. getOwnProperty Symbols 방법 은 하나의 배열 을 되 돌려 줍 니 다. 구성원 은 현재 대상 의 모든 속성 명 으로 사용 되 는 Symbol 값 입 니 다.
    var obj = {};
    var a = Symbol('a');
    var b = Symbol('b');
    
    obj[a] = 'Hello';
    obj[b] = 'World';
    
    var objectSymbols = Object.getOwnPropertySymbols(obj);
    
    console.log(objectSymbols)
    //   [Symbol(a), Symbol(b)]
    
    for (var i in obj) {//           Symbol
        console.log(i); //    
    }
    
    console.log(Object.getOwnPropertyNames(obj))//           Symbol
    //   []

    Reflect.ownKeys
    Reflect. ownKeys 방법 은 일반적인 키 이름과 Symbol 키 를 포함 하여 모든 종류의 키 이름 을 되 돌려 줍 니 다.
    let obj = {
        [Symbol('my_key')]: 1,
        enum: 2,
        nonEnum: 3
    };
    
    console.log(Reflect.ownKeys(obj))
    //    ["enum", "nonEnum", Symbol(my_key)]

    Symbol.for()
    Symbol. for 방법 은 문자열 을 매개 변수 로 받 아들 인 다음 이 매개 변 수 를 이름 으로 하 는 Symbol 값 이 있 는 지 검색 합 니 다.있 으 면 이 Symbol 값 을 되 돌려 줍 니 다. 그렇지 않 으 면 이 문자열 이름 의 Symbol 값 을 새로 만 들 고 되 돌려 줍 니 다.
    var s1 = Symbol.for('foo');
    var s2 = Symbol.for('foo');
    
    console.log(s1 === s2) // true
    
    
    console.log(Symbol.for("bar") === Symbol.for("bar"))
    // true
    
    console.log(Symbol("bar") === Symbol("bar"))
    // false

    Symbol. for () 와 Symbol () 두 가지 표기 법 은 모두 새로운 Symbol 을 생 성 합 니 다.이들 의 차 이 는 전 자 는 전체 환경 에 등록 되 어 검색 할 수 있 고 후 자 는 그렇지 않다 는 것 이다.Symbol. for () 는 호출 할 때마다 새로운 Symbol 형식의 값 을 되 돌려 주지 않 고 주어진 key 가 존재 하 는 지 확인 합 니 다. 존재 하지 않 으 면 새 값 을 만 듭 니 다.
    인 스 턴 스: 모듈 의 Singleton 모드
    Singleton 모드 는 같은 종 류 를 호출 하 는 것 을 말 합 니 다. 언제든지 같은 인 스 턴 스 로 돌아 갑 니 다.
    노드 에 대해 말하자면 모듈 파일 은 하나의 클래스 로 볼 수 있다.이 모듈 파일 을 실행 할 때마다 같은 인 스 턴 스 로 돌아 갈 것 을 어떻게 보장 합 니까?
  • 인 스 턴 스 를 최상 위 대상 global
  • 에 올 려 놓 습 니 다.
    // mod.js
    function A() {
        this.foo = 'hello';
    }
    
    if (!global._foo) {
        global._foo = new A();
    }
    
    module.exports = global._foo;

    변수 a 는 언제든지 A 의 같은 인 스 턴 스 를 불 러 옵 니 다.
    var a = require('./mod.js');
    console.log(a.foo);
  • 하지만 여기 문제 가 있 습 니 다. 전역 변수 global.foo 는 쓸 수 있 습 니 다. 모든 파일 을 수정 할 수 있 습 니 다.
  • var a = require('./mod.js');
    global._foo = 123;//       global._foo

    위의 코드 는 다른 스 크 립 트 에 mod. js 를 불 러 올 수 있 습 니 다.
    이런 상황 을 방지 하기 위해 서 우 리 는 Symbol 을 사용 할 수 있다.
    // mod.js
    const FOO_KEY = Symbol.for('foo'); //Symbol.for                 Symbol 
    
    function A() {
      this.foo = 'hello';
    }
    
    if (!global[FOO_KEY]) {
      global[FOO_KEY] = new A();
    }
    
    module.exports = global[FOO_KEY];

    위의 코드 에 서 는 global [FOO KEY] 이 의도 치 않 게 덮어 쓰 지 는 않 지만 고 칠 수 있 습 니 다.
    var a = require('./mod.js');
    global[Symbol.for('foo')] = 123;

    키 이름 이 Symbol 방법 으로 생 성 되면 외부 에서 이 값 을 참조 할 수 없 으 며, 물론 고 칠 수 없습니다.
    // mod.js
    const FOO_KEY = Symbol('foo');//        ,  Symbol  
    
    //        ……

    위의 코드 는 다른 스 크 립 트 에서 FOO 를 참조 할 수 없 게 합 니 다.KEY。하지만 이 스 크 립 트 를 여러 번 실행 하면 매번 받 는 FOO 가 문제 다.케 이 는 다 달라.Node 는 스 크 립 트 의 실행 결 과 를 캐 시 합 니 다. 일반적으로 같은 스 크 립 트 를 여러 번 실행 하지 않 지만 사용 자 는 수 동 으로 캐 시 를 삭제 할 수 있 기 때문에 신뢰 할 수 있 는 것 도 아 닙 니 다.
    내 장 된 Symbol 값
    Symbol.hasInstance
    대상 의 Symbol. hasInstance 속성 은 내부 방법 을 가리 키 고 있 습 니 다.다른 대상 이 인 스 턴 스 of 연산 자 를 사용 하여 이 대상 의 인 스 턴 스 여 부 를 판단 할 때 이 방법 을 사용 합 니 다.예 를 들 어 foo instanceof Foo 는 언어 내부 에서 실제 호출 된 것 은 Foo[Symbol.hasInstance](foo) 이다.
    class MyClass {
        [Symbol.hasInstance](foo) {//instanceof         
            return foo instanceof Array;
        }
    }
    //   instanceof
    console.log([1, 2, 3] instanceof new MyClass()) //   true

    Symbol.isConcatSpreadable
    대상 의 Symbol. isConcatSpreadable 속성 은 불 값 과 같 습 니 다. 이 대상 이 Array. prototype. concat () 를 사용 할 때 펼 칠 수 있 는 지 여 부 를 표시 합 니 다.
    배열 의 기본 동작 은 펼 칠 수 있 습 니 다.
    let arr1 = ['c', 'd'];
    console.log(['a', 'b'].concat(arr1, 'e')) // ['a', 'b', 'c', 'd', 'e']
    console.log(arr1[Symbol.isConcatSpreadable]) // undefined
    
    let arr2 = ['c', 'd'];
    arr2[Symbol.isConcatSpreadable] = false;
    console.log(arr2[Symbol.isConcatSpreadable]);//  false
    console.log(['a', 'b'].concat(arr2, 'e')) // ['a', 'b', ['c','d'], 'e']

    Symbol.species
    대상 의 Symbol. species 속성 은 현재 대상 의 구조 함 수 를 가리킨다.인 스 턴 스 를 만 들 때 기본적으로 이 방법 을 호출 합 니 다. 즉, 이 속성 이 돌아 오 는 함 수 를 구조 함수 로 하여 새로운 인 스 턴 스 대상 을 만 듭 니 다.
    class MyArray extends Array {
        //      Array      
        //        MyArray   
        static get [Symbol.species]() { return this; }//        get   Symbol.species  
    }
    var a = new MyArray(1,2,3);
    var mapped = a.map(x => x * x);
    
    //    MyArray    ,          Array,    true
    console.log(mapped instanceof MyArray) // true
    console.log(mapped instanceof Array) // true
    
    
    //       Array  ,      Array true
     static get [Symbol.species]() { return Array; }

    Symbol.match
    대상 의 Symbol. match 속성 은 함 수 를 가리 키 고 있 습 니 다.str. match (my Object) 를 실행 할 때 이 속성 이 존재 하면 호출 하여 이 방법의 반환 값 을 되 돌려 줍 니 다.
    String.prototype.match(regexp)
    //    
    regexp[Symbol.match](this)
    class MyMatcher {
      [Symbol.match](string) {
        return 'hello world'.indexOf(string);
      }
    }
    
    'e'.match(new MyMatcher()) // 1( 0       ,1    )

    Symbol.replace
    대상 의 Symbol. replace 속성 은 하나의 방법 을 가리 키 며, 대상 이 String. prototype. replace 방법 으로 호출 될 때 이 방법의 반환 값 을 되 돌려 줍 니 다.
    String.prototype.replace(searchValue, replaceValue)
    //    
    searchValue[Symbol.replace](this, replaceValue)
           。
    const obj = {};
    obj[Symbol.replace] = (...s) => console.log(s);
    
    'Hello'.replace(obj, 'World') // ["Hello", "World"]

    Symbol. replace 방법 은 두 개의 인 자 를 받 을 수 있 습 니 다. 첫 번 째 인 자 는 replace 방법 이 작용 하고 있 는 대상 입 니 다. 위의 예 는 Hello 이 고 두 번 째 인 자 는 교 체 된 값 입 니 다. 위의 예 는 World 입 니 다.
    Symbol.search
    대상 의 Symbol. search 속성 은 하나의 방법 을 가리 키 며, 대상 이 String. prototype. search 방법 으로 호출 될 때 이 방법의 반환 값 을 되 돌려 줍 니 다.
    String.prototype.search(regexp)
    //    
    regexp[Symbol.search](this)
    class MySearch {
        constructor(value) {
            this.value = value;
        }
        [Symbol.search](string) {
            return string.indexOf(this.value);
        }
    }
    console.log('foobar'.search(new MySearch('foo'))) // 0

    Symbol.split
    대상 의 Symbol. split 속성 은 하나의 방법 을 가리 키 며, 대상 이 String. prototype. split 방법 으로 호출 될 때 이 방법의 반환 값 을 되 돌려 줍 니 다.
    String.prototype.split(separator, limit)
    //    
    separator[Symbol.split](this, limit)
    class MySplitter {
        constructor(value) {
            this.value = value;
        }
        [Symbol.split](string) {
            var index = string.indexOf(this.value);
            if (index === -1) {
                return string;
            }
            return [
                string.substr(0, index),
                string.substr(index + this.value.length)
            ];
        }
    }
    
    console.log('foobar'.split(new MySplitter('foo')))
    // ['', 'bar']
    
    console.log('foobar'.split(new MySplitter('bar')))
    // ['foo', '']
    
    console.log('foobar'.split(new MySplitter('baz')))
    // 'foobar'

    위의 방법 은 Symbol. split 방법 을 사용 하여 문자열 대상 의 split 방법 을 다시 정의 합 니 다.
    Symbol.iterator
    대상 의 Symbol. iterator 속성 은 이 대상 의 기본 달력 방법 을 가리 키 고 있 습 니 다.
    var myIterable = {};
    myIterable[Symbol.iterator] = function* () {
      yield 1;
      yield 2;
      yield 3;
    };
    
    [...myIterable] // [1, 2, 3]

    대상 이 for... of 순환 을 할 때 Symbol. iterator 방법 을 사용 하여 이 대상 의 기본 달력 을 되 돌려 줍 니 다.
    Symbol.toPrimitive
    대상 의 Symbol. toPrimitive 속성 은 하나의 방법 을 가리킨다.이 대상 이 원본 형식의 값 으로 바 뀌 었 을 때 이 방법 을 사용 하여 해당 대상 에 대응 하 는 원본 형식 값 을 되 돌려 줍 니 다.
    Symbol. toPrimitive 가 호출 될 때 현재 연산 모드 를 나타 내 는 문자열 인 자 를 받 습 니 다. 모두 세 가지 모드 가 있 습 니 다.
    Number: 이 장 소 는 수치 String 으로 바 꿔 야 합 니 다. 이 장 소 는 문자열 로 바 꿔 야 합 니 다. Default: 이 장 소 는 수치 로 바 꿀 수도 있 고 문자열 로 바 꿀 수도 있 습 니 다.
    let obj = {
        [Symbol.toPrimitive](hint) {
            switch (hint) {
                case 'number':
                    return 123;
                case 'string':
                    return 'str';
                case 'default':
                    return 'default';
                default:
                    throw new Error();
            }
        }
    };
    
    console.log(2 * obj) // 246
    console.log(3 + obj) // '3default'
    console.log(obj == 'default') // true
    console.log(String(obj)) // 'str'

    Symbol.toStringTag
    대상 의 Symbol. toStringTag 속성 은 하나의 방법 을 가리킨다.이 대상 에서 Object. prototype. toString 방법 을 호출 할 때 이 속성 이 존재 하면 반환 값 은 toString 방법 이 되 돌아 오 는 문자열 에 나타 나 대상 의 종 류 를 표시 합 니 다.즉, 이 속성 은 [object Object] 나 [object Array] 의 object 뒤의 문자열 을 맞 출 수 있 습 니 다.
    //   
    console.log(({[Symbol.toStringTag]: 'Foo'}.toString()))
    // "[object Foo]"
    
    //   
    class Collection {
        get [Symbol.toStringTag]() {
            return 'xxx';
        }
    }
    var x = new Collection();
    console.log(Object.prototype.toString.call(x)) // "[object xxx]"

    ES6 에 내 장 된 대상 을 추가 한 Symbol. toStringTag 속성 값 은 다음 과 같 습 니 다.
    JSON[Symbol.toStringTag]:'JSON'
    Math[Symbol.toStringTag]:'Math'
    Module  M[Symbol.toStringTag]:'Module'
    ArrayBuffer.prototype[Symbol.toStringTag]:'ArrayBuffer'
    DataView.prototype[Symbol.toStringTag]:'DataView'
    Map.prototype[Symbol.toStringTag]:'Map'
    Promise.prototype[Symbol.toStringTag]:'Promise'
    Set.prototype[Symbol.toStringTag]:'Set'
    %TypedArray%.prototype[Symbol.toStringTag]:'Uint8Array' 
    WeakMap.prototype[Symbol.toStringTag]:'WeakMap'
    WeakSet.prototype[Symbol.toStringTag]:'WeakSet'
    %MapIteratorPrototype%[Symbol.toStringTag]:'Map Iterator'
    %SetIteratorPrototype%[Symbol.toStringTag]:'Set Iterator'
    %StringIteratorPrototype%[Symbol.toStringTag]:'String Iterator'
    Symbol.prototype[Symbol.toStringTag]:'Symbol'
    Generator.prototype[Symbol.toStringTag]:'Generator'
    GeneratorFunction.prototype[Symbol.toStringTag]:'GeneratorFunction'

    참조 참조:
  • Symbol
  • 좋은 웹페이지 즐겨찾기