> 웹 프론트엔드 > JS 튜토리얼 > 왜 Symbol 유형이 있습니까? 사용하는 방법?

왜 Symbol 유형이 있습니까? 사용하는 방법?

青灯夜游
풀어 주다: 2022-03-22 11:04:51
앞으로
2760명이 탐색했습니다.

심볼이란 무엇인가요? 왜 그런 것이 있습니까? 다음 글에서는 JavaScript의 Symbol 유형을 소개하고 이를 사용하는 방법에 대해 설명하겠습니다.

왜 Symbol 유형이 있습니까? 사용하는 방법?

심볼이란 무엇인가요? 왜 그런 것이 있습니까?

Symbol(심볼)은 ES6의 새로운 데이터 유형입니다. 기호는 기본 값(기본 데이터 유형)이며 기호 인스턴스는 고유하고 변경할 수 없습니다. 이는 개체 속성이 속성 충돌 위험 없이 고유 식별자를 사용하도록 보장하기 위해 고유하게 표시한 다음 문자열이 아닌 형식의 개체 속성으로 사용되기 때문에 생성됩니다. [관련 권장사항: javascript 학습 튜토리얼]

Usage

1. 기본 사용법

기호는 Symbol() 함수를 사용하여 초기화해야 합니다. 기호 자체는 기본 유형이므로 typeof 연산자는 기호에 대한 기호를 반환합니다.

let sym = Symbol();
console.log(typeof sym); // symbol
로그인 후 복사

Symbol() 함수는 설명할 문자열 매개변수를 받을 수 있으며, 그런 다음 이 문자열을 사용하여 코드를 디버그할 수 있습니다. 그러나 여러 Symbol() 함수가 동일한 매개변수를 허용하더라도 해당 값은 동일하지 않다는 점은 주목할 가치가 있습니다.

let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");

console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false
로그인 후 복사

2 전역 기호 레지스트리 사용

코드의 여러 위치에서 동일한 Symbol 인스턴스를 사용해야 하는 경우 문자열을 전달한 다음 Symbol.for() 메서드를 사용하여 재사용할 수 있습니다. Symbol은 싱글톤 모드와 유사합니다. 처음으로 Symbol.for()를 사용할 때 전달된 매개변수를 기반으로 Symbol.for()를 사용하여 동일한 인스턴스가 생성되었는지 전역적으로 검색합니다. 그렇다면 재사용합니다. . 그렇지 않은 경우 새 인스턴스를 만드세요

let fooGlobalSymbol = Symbol.for("foo"); // 创建新符号
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
로그인 후 복사

Symbol.for()로 생성된 인스턴스와 Symbol()으로 생성된 인스턴스의 차이점:Symbol()로 생성된 인스턴스는 항상 고유하며 변경되지 않습니다. 전달 입력 매개변수는 동일하고 다른 인스턴스와 동일하지만, 매개변수가 동일하면 Symbol.for()에 의해 생성된 인스턴스는 동일한 Symbol 인스턴스를 공유하므로 동일하게 됩니다

let fooSymbol = Symbol("foo");
let otherFooSymbol = Symbol("foo");
console.log(fooSymbol == otherFooSymbol); // false

let fooGlobalSymbol = Symbol.for("foo"); // 创建新符号
let otherFooGlobalSymbol = Symbol.for("foo"); // 重用已有符号
console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true
로그인 후 복사

3. 기호를 속성으로

객체의 속성은 일반적으로 문자열 형식이지만 실제로 기호 인스턴스를 속성으로 사용할 수도 있습니다. 이 경우 새 속성이 이전 속성을 덮어쓰지 않는다는 장점이 있습니다

let s1 = Symbol("foo"),
  s2 = Symbol("bar"),
  s3 = Symbol("baz"),
  s4 = Symbol("qux");
let o = {
  [s1]: "foo val",
};
// 这样也可以:o[s1] = 'foo val';
console.log(o);
// {Symbol(foo): foo val}
Object.defineProperty(o, s2, { value: "bar val" });
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val}
Object.defineProperties(o, {
  [s3]: { value: "baz val" },
  [s4]: { value: "qux val" },
});
console.log(o);
// {Symbol(foo): foo val, Symbol(bar): bar val,
// Symbol(baz): baz val, Symbol(qux): qux val}
로그인 후 복사

참고: 생성 Symbol 인스턴스가 객체 속성으로 사용될 때 처음에 수신용 변수를 선언하지 않고 기호가 변경되면 객체의 모든 기호 속성을 탐색하여 해당 속성 키를 찾아야 합니다.

let o = {
  [Symbol("foo")]: "foo val",
  [Symbol("bar")]: "bar val",
};
console.log(o);
// {Symbol(foo): "foo val", Symbol(bar): "bar val"}
let barSymbol = Object.getOwnPropertySymbols(o).find(symbol => symbol.toString().match(/bar/));
console.log(barSymbol);
// Symbol(bar)
로그인 후 복사

4 . 일반적으로 사용되는 내장 기호

ES6 언어의 내부 동작을 노출하기 위해 일반적으로 사용되는 여러 내장 기호(잘 알려진 기호)도 도입되었으며 개발자는 이러한 동작에 직접 액세스하거나 재정의하거나 시뮬레이션할 수 있습니다. 이러한 기본 속성을 수정하면 일부 작업의 최종 실행 결과가 변경될 수 있습니다. 예를 들어 for-of 루프는 해당 객체의 Symbol.iterator 속성을 사용하므로 사용자 정의 객체에서 Symbol.iterator 값을 다시 정의하여 객체를 반복할 때 for-of의 동작을 변경할 수 있습니다.

5.Symbol.asyncIterator

는 실제로 Promise를 반환하는 생성기이며 일반적으로

6의 대기에 사용됩니다. Symbol.hasInstance

ECMAScript 사양에 따르면 이 기호는 " 메소드, 이 메소드는 for-await-of 문에서 사용되는 객체의 기본 AsyncIterator를 반환합니다. 즉, 이 기호는 비동기 반복자 API를 구현하는 함수를 나타냅니다.

이 속성은 Function의 프로토타입에 정의되어 있습니다. 우리 모두는 객체 인스턴스가 특정 생성자에 속하는지 여부를 확인하는 데 objectof 연산자를 사용할 수 있다는 것을 알고 있습니다. 원칙은 instanceof 연산자가 관계를 결정하기 위해 Symbol.hasInstance 함수를 사용한다는 것입니다

function Foo() {}
let f = new Foo();
console.log(f instanceof Foo); // true
class Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true
로그인 후 복사

함수의 Symbol.hasInstance 속성을 재정의하면 인스턴스of 메서드가 예상치 못한 것을 반환하도록 할 수 있습니다

class Bar {}
class Baz extends Bar {
  static [Symbol.hasInstance]() {
    return false;
  }
}
let b = new Baz();
console.log(Bar[Symbol.hasInstance](b)); // true
console.log(b instanceof Bar); // true
console.log(Baz[Symbol.hasInstance](b)); // false
console.log(b instanceof Baz); // false
로그인 후 복사

Symbol.isConcatSpreadabl

이 속성은 Array의 프로토타입에 정의됩니다.

ECMAScript 사양에 따르면 속성으로서의 이 기호는 "부울 값"을 나타냅니다. true인 경우 객체가 Array.prototype.concat( ) ". ES6의 Array.prototype.concat() 메소드는 수신된 객체 유형에 따라 유사 배열(의사 배열) 객체를 배열 인스턴스로 연결하는 방법을 선택합니다. 따라서 Symbol.isConcatSpreadable 값을 수정하면 이 동작을 수정할 수 있습니다.

Symbol.isConcatSpreadable 해당 효과

false: 배열에 전체 객체 추가 true: 배열에 전체 쌍 추가

let initial = ["foo"];
let array = ["bar"];
console.log(array[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(array)); // ['foo', 'bar']
array[Symbol.isConcatSpreadable] = false;
console.log(initial.concat(array)); // ['foo', Array(1)]
let arrayLikeObject = { length: 1, 0: "baz" };
console.log(arrayLikeObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(arrayLikeObject)); // ['foo', {...}]

arrayLikeObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(arrayLikeObject)); // ['foo', 'baz']
let otherObject = new Set().add("qux");
console.log(otherObject[Symbol.isConcatSpreadable]); // undefined
console.log(initial.concat(otherObject)); // ['foo', Set(1)]
otherObject[Symbol.isConcatSpreadable] = true;
console.log(initial.concat(otherObject)); // ['foo']
로그인 후 복사

8 Symbol.iterator

ECMAScript 사양에 따르면, 이 기호는 속성으로 "객체의 기본 반복자를 반환하는 메서드입니다. for-of 문에서 사용됩니다"

该属性会返回一个 Generator 函数,for of 就会依次的去调用 next()方法,这就是为什么 for of 可以使用在某些对象身上。

class Emitter {
  constructor(max) {
    this.max = max;
    this.idx = 0;
  }
  *[Symbol.iterator]() {
    while (this.idx < this.max) {
      yield this.idx++;
    }
  }
}
function count() {
  let emitter = new Emitter(5);
  for (const x of emitter) {
    console.log(x);
  }
}
count();
// 0
// 1
// 2
// 3
// 4
로그인 후 복사

9. Symbol.match

根据 ECMAScript 规范,这个符号作为一个属性表示“一个正则表达式方法,该方法用正则表达式去匹配字符串。由 String.prototype.match()方法使用”。

String.prototype.match()方法会使用以 Symbol.match 为键的函数来对正则表达式求值。所以更改一个正则表达式的 Symbol.match 属性,可以让 String.prototype.match()得到你想要的值

console.log(RegExp.prototype[Symbol.match]);
// ƒ [Symbol.match]() { [native code] }
console.log("foobar".match(/bar/));
// ["bar", index: 3, input: "foobar", groups: undefined]

class FooMatcher {
  static [Symbol.match](target) {
    return target.includes("foo");
  }
}
console.log("foobar".match(FooMatcher)); // true
console.log("barbaz".match(FooMatcher)); // false
class StringMatcher {
  constructor(str) {
    this.str = str;
  }
  [Symbol.match](target) {
    return target.includes(this.str);
  }
}
console.log("foobar".match(new StringMatcher("foo"))); // true
console.log("barbaz".match(new StringMatcher("qux"))); // false
로그인 후 복사

11. Symbol.search

这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中 匹配正则表达式的索引。由 String.prototype.search()方法使用”

12. Symbol.species

这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构 造函数”。

13. Symbol.split

这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表 达式的索引位置拆分字符串。由 String.prototype.split()方法使用”。

14. Symbol.toPrimitive

这个符号作为一个属性表示“一个方法,该方法将对象转换为相应的原始 值。由 ToPrimitive 抽象操作使用”

15. Symbol.toStringTag

这个符号作为一个属性表示“一个字符串,该字符串用于创建对象的默认 字符串描述。由内置方法 Object.prototype.toString()使用”

16. Symbol.unscopables

这个符号作为一个属性表示“一个对象,该对象所有的以及继承的属性, 都会从关联对象的 with 环境绑定中排除

更多编程相关知识,请访问:编程视频!!

위 내용은 왜 Symbol 유형이 있습니까? 사용하는 방법?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿