심볼이란 무엇인가요? 왜 그런 것이 있습니까? 다음 글에서는 JavaScript의 Symbol 유형을 소개하고 이를 사용하는 방법에 대해 설명하겠습니다.
Symbol(심볼)은 ES6의 새로운 데이터 유형입니다. 기호는 기본 값(기본 데이터 유형)이며 기호 인스턴스는 고유하고 변경할 수 없습니다. 이는 개체 속성이 속성 충돌 위험 없이 고유 식별자를 사용하도록 보장하기 위해 고유하게 표시한 다음 문자열이 아닌 형식의 개체 속성으로 사용되기 때문에 생성됩니다. [관련 권장사항: javascript 학습 튜토리얼]
기호는 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
코드의 여러 위치에서 동일한 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
객체의 속성은 일반적으로 문자열 형식이지만 실제로 기호 인스턴스를 속성으로 사용할 수도 있습니다. 이 경우 새 속성이 이전 속성을 덮어쓰지 않는다는 장점이 있습니다
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)
ES6 언어의 내부 동작을 노출하기 위해 일반적으로 사용되는 여러 내장 기호(잘 알려진 기호)도 도입되었으며 개발자는 이러한 동작에 직접 액세스하거나 재정의하거나 시뮬레이션할 수 있습니다. 이러한 기본 속성을 수정하면 일부 작업의 최종 실행 결과가 변경될 수 있습니다. 예를 들어 for-of 루프는 해당 객체의 Symbol.iterator 속성을 사용하므로 사용자 정의 객체에서 Symbol.iterator 값을 다시 정의하여 객체를 반복할 때 for-of의 동작을 변경할 수 있습니다.
는 실제로 Promise를 반환하는 생성기이며 일반적으로
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
이 속성은 Array의 프로토타입에 정의됩니다.
ECMAScript 사양에 따르면 속성으로서의 이 기호는 "부울 값"을 나타냅니다. true인 경우 객체가 Array.prototype.concat( ) ". ES6의 Array.prototype.concat() 메소드는 수신된 객체 유형에 따라 유사 배열(의사 배열) 객체를 배열 인스턴스로 연결하는 방법을 선택합니다. 따라서 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']
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
根据 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
这个符号作为一个属性表示“一个正则表达式方法,该方法返回字符串中 匹配正则表达式的索引。由 String.prototype.search()方法使用”
这个符号作为一个属性表示“一个函数值,该函数作为创建派生对象的构 造函数”。
这个符号作为一个属性表示“一个正则表达式方法,该方法在匹配正则表 达式的索引位置拆分字符串。由 String.prototype.split()方法使用”。
这个符号作为一个属性表示“一个方法,该方法将对象转换为相应的原始 值。由 ToPrimitive 抽象操作使用”
这个符号作为一个属性表示“一个字符串,该字符串用于创建对象的默认 字符串描述。由内置方法 Object.prototype.toString()使用”
这个符号作为一个属性表示“一个对象,该对象所有的以及继承的属性, 都会从关联对象的 with 环境绑定中排除
更多编程相关知识,请访问:编程视频!!
위 내용은 왜 Symbol 유형이 있습니까? 사용하는 방법?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!