아시다시피 ECMAScript 6에 새로운 Symbol 프리미티브 유형 을 포함 할 계획입니다 (다른 미친 것들은 말할 것도 없습니다). 나는 :symbol
루비 의 개념이 불필요 하다고 항상 생각했다 . JavaScript 에서처럼 일반 문자열을 쉽게 사용할 수 있습니다. 그리고 이제 그들은 JS의 것들을 복잡하게하기로 결정했습니다.
나는 동기를 이해하지 못한다. 자바 스크립트에서 실제로 기호가 필요한지 설명해 줄 수 있습니까?
답변
Javascript에 심볼을 도입하려는 원래 동기는 개인 속성 을 활성화하는 것이 었습니다 .
불행하게도, 그들은 심각하게 다운 그레이드되었습니다. 예를 들어, Object.getOwnPropertySymbols
프록시를 사용하여 리플렉션을 통해 찾을 수 있으므로 더 이상 비공개 입니다.
이제는 고유 한 기호 로 알려져 있으며 속성 간의 이름 충돌을 피하기위한 용도로만 사용됩니다. 예를 들어 ECMAScript 자체는 사용자 이름과 충돌 할 위험없이 객체에 배치 할 수있는 특정 방법 (예 : 반복 프로토콜 정의)을 통해 확장 후크를 도입 할 수 있습니다.
언어에 기호를 추가하려는 동기가 충분히 강력한 지 여부는 논란의 여지가 있습니다.
답변
기호는 진정한 개인 정보 보호를 보장하지는 않지만 객체의 공용 속성과 내부 속성을 분리하는 데 사용할 수 있습니다. Symbol
개인 속성을 갖는 데 사용할 수있는 예를 살펴 보겠습니다 .
객체의 속성이 비공개가 아닌 경우를 예로 들어 봅시다.
var Pet = (function() {
function Pet(type) {
this.type = type;
}
Pet.prototype.getType = function() {
return this.type;
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null
위의 Pet
클래스 속성 type
은 비공개가 아닙니다. 비공개로하려면 클로저를 만들어야합니다. 아래 예제 type
는 클로저를 사용하여 비공개로 만드는 방법을 보여줍니다 .
var Pet = (function() {
function Pet(type) {
this.getType = function(){
return type;
};
}
return Pet;
}());
var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog
위의 접근 방식의 단점 : Pet
생성 된 각 인스턴스 에 대해 추가적인 폐쇄를 도입하여 성능을 저하시킬 수 있습니다.
이제 우리는 소개 Symbol
합니다. 이를 통해 불필요한 추가 폐쇄를 사용하지 않고 개인 재산을 만들 수 있습니다. 아래 코드 예 :
var Pet = (function() {
var typeSymbol = Symbol('type');
function Pet(type) {
this[typeSymbol] = type;
}
Pet.prototype.getType = function(){
return this[typeSymbol];
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog
답변
Symbols
객체에서 고유 한 속성 이름으로 사용할 수있는 새롭고 특별한 종류의 객체입니다. Symbol
대신에를 사용 string
하면 서로 다른 모듈이 서로 충돌하지 않는 속성을 만들 수 있습니다. Symbols
은 (는) 비공개로 만들 수 있으므로 아직에 직접 액세스하지 않은 사람은 속성에 액세스 할 수 없습니다 Symbol
.
Symbols
새로운 프리미티브 입니다. 그냥 같은 number
, string
그리고 boolean
프리미티브 Symbol
를 생성하는 데 사용할 수있는 기능을 가지고있다. 다른 프리미티브와 달리 Symbols
리터럴 구문은 없습니다 (예 : how string
have ''
).이를 생성하는 유일한 방법 Symbol
은 다음과 같은 방법으로 생성자를 사용하는 것입니다.
let symbol = Symbol();
실제로 Symbol
는 객체에 속성을 첨부하는 약간 다른 방법 입니다 . 상속 된 모든 항목에 나타나는 Symbols
것처럼 표준 메서드를 쉽게 제공 할 수 있습니다 .Object.prototype.hasOwnProperty
Object
다음은 Symbol
기본 유형 의 장점 중 일부입니다 .
Symbols
디버깅 기능이 내장되어 있습니다
Symbols
콘솔에 로깅 할 때 인생을 조금 더 쉽게하기 위해 디버깅에 실제로 사용되는 설명을 제공 할 수 있습니다.
Symbols
Object
키로 사용할 수 있습니다
이곳이 Symbol
정말 흥미로워 지는 곳 입니다. 그것들은 물체와 크게 얽혀 있습니다. Symbol
객체에 키로 할당 할 수 있습니다. 즉, 객체에 고유 한 수를 무제한으로 할당 할 수 Symbol
있으며 string
키 또는 다른 고유 한 객체와 충돌하지 않도록 보장 할 수 있습니다 Symbols
.
Symbols
고유 한 값으로 사용할 수 있습니다.
하자가 같은 여러 개의 로그 수준을 포함하는 로깅 라이브러리가 가정 logger.levels.DEBUG
, logger.levels.INFO
, logger.levels.WARN
등을. ES5 코드에서는 이것을 string
s (so logger.levels.DEBUG === 'debug'
) 또는 number
s ( logger.levels.DEBUG === 10
)로 만들고 싶습니다 . 이러한 값은 고유 한 값이 아니기 때문에 이상적이지 않지만 Symbol
s는 이상적입니다 ! 따라서 logger.levels
간단히 다음과 같습니다.
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
이 위대한 기사 에서 더 많은 것을 읽으십시오 .
답변
이 게시물은 Symbol()
내가 찾거나 만들 수있는 실제 예제와 내가 찾을 수있는 사실 및 정의와 함께 제공됩니다.
TLDR;
는 Symbol()
ECMAScript를 6 (ES6)의 방출 도입 데이터 형식이다.
Symbol에 대한 두 가지 흥미로운 사실이 있습니다.
-
리터럴이없는 JavaScript의 첫 번째 데이터 유형 및 유일한 데이터 유형
-
로 정의 된 모든 변수
Symbol()
는 고유 한 콘텐츠를 얻지 만 실제로는 비공개 가 아닙니다 . -
모든 데이터에는 자체 Symbol 이 있으며 동일한 데이터에 대해 Symbols는 동일 합니다. 다음 단락에서 더 많은 정보, 그렇지 않으면 TLRD가 아닙니다. 🙂
심볼을 어떻게 초기화합니까?
1. 디버깅 가능한 값을 가진 고유 식별자를 얻으려면
이 방법으로 할 수 있습니다 :
var mySymbol1 = Symbol();
또는이 방법 :
var mySymbol2 = Symbol("some text here");
"some text here"
문자열이 기호에서 추출 할 수 없습니다, 그것은 디버깅 목적으로 만 설명입니다. 어떤 식 으로든 기호 동작을 변경하지 않습니다. 비록 당신이 할 수는 console.log
있지만 (값은 디버깅을위한 것이므로 다른 로그 항목으로 그 로그를 착각하지 않도록)
console.log(mySymbol2);
// Symbol(some text here)
2. 일부 문자열 데이터에 대한 기호를 얻으려면
이 경우 심볼의 값이 실제로 고려되며이 방식으로 두 심볼이 고유하지 않을 수 있습니다.
var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!
이러한 기호를 “두 번째 유형”기호라고합니다. Symbol(data)
어떤 식 으로든 “첫 번째 유형”기호 (예 :로 정의 된 기호)와 교차하지 않습니다 .
다음 두 단락은 첫 번째 유형 기호 에만 해당 됩니다.
이전 데이터 유형 대신 Symbol을 사용하면 어떤 이점이 있습니까?
먼저 표준 데이터 유형 인 객체를 고려해 봅시다. 키-값 쌍을 정의하고 키를 지정하여 값에 액세스 할 수 있습니다.
var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan
Peter라는 이름을 가진 두 사람이 있다면 어떨까요?
이것을하는 것 :
var persons = {"peter":"first", "peter":"pan"};
별로 이해가되지 않습니다.
따라서 같은 이름을 가진 두 명의 완전히 다른 사람의 문제인 것 같습니다. 그런 다음 new를 참조하십시오 Symbol()
. 실생활의 사람 과 같습니다. 모든 사람은 독특 하지만 이름은 동일 할 수 있습니다. 두 “사람”을 정의합시다.
var a = Symbol("peter");
var b = Symbol("peter");
이제 같은 이름을 가진 두 사람이 있습니다. 우리의 사람들은 실제로 다른가? 그들은; 당신은 이것을 확인할 수 있습니다 :
console.log(a == b);
// false
우리는 어떻게 유익합니까?
우리는 다른 사람을 위해 당신의 물건에 두 개의 항목을 만들 수 있으며 어떤 식 으로든 착각 할 수 없습니다.
var firstPerson = Symbol("peter");
var secondPerson = Symbol("peter");
var persons = {[firstPerson]:"first", [secondPerson]:"pan"};
참고 :
객체를 문자열 화하면JSON.stringify
Symbol로 키로 초기화 된 모든 쌍이 삭제됩니다.
실행Object.keys
은 그러한Symbol()->value
쌍을 반환하지 않습니다 .
이 초기화를 사용하면 첫 번째 사람과 두 번째 사람의 항목을 착각하는 것은 절대 불가능합니다. 전화 console.log
하면 두 번째 이름이 올바르게 출력됩니다.
console.log(persons[a]);
// first
console.log(persons[b]);
// pan
객체에 사용될 때 열거 불가능한 속성을 정의하는 것과 어떻게 다른가요?
실제로, 숨겨 Object.keys
지고 열거 될 속성을 정의하는 방법이 이미 존재했습니다 . 여기있어:
var anObject = {};
var fruit = "apple";
Object.defineProperty( anObject, fruit, {
enumerable: false,
value: "green"
});
어떤 차이가 Symbol()
있습니까? 차이점은 Object.defineProperty
일반적인 방법으로 속성을 정의 할 수 있다는 것입니다.
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green
그리고 이전 단락에서와 같이 Symbol로 정의 된 경우 :
fruit = Symbol("apple");
변수를 알고있는 경우에만 값을받을 수 있습니다.
console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined
또한 키 아래에 다른 속성을 정의 "apple"
하면 개체가 오래된 개체를 삭제하게됩니다 (하드 코딩 된 경우 오류가 발생할 수 있음). 더 이상 사과는 없습니다! 그 유감. 이전 단락을 참조하면 기호는 고유하며 Symbol()
고유하게 키를 정의합니다 .
타입 변환 및 확인
-
다른 데이터 형식과 달리
Symbol()
합니다. -
호출하여 원시 데이터 유형을 기반으로 심볼을 “만들”수 있습니다
Symbol(data)
. -
유형 확인 측면에서 아무 것도 변경되지 않습니다.
function isSymbol ( variable ) { return typeof someSymbol === "symbol"; } var a_Symbol = Symbol("hey!"); var totally_Not_A_Symbol = "hey"; console.log(isSymbol(a_Symbol)); //true console.log(isSymbol(totally_Not_A_Symbol)); //false
답변
내가 보는 방법은 다음과 같습니다. 심볼은 Object.keys () 및 JSON.stringify ()와 같이 널리 사용되는 일부 메서드를 통해 객체의 키 / 속성이 노출되지 않도록하여 ‘추가 수준의 개인 정보 보호’를 제공합니다.
var age = Symbol(); // declared in another module perhaps?
class Person {
constructor(n,a){
this.name = n;
this[age] = a;
}
introduce(){
console.log(`My name is ${this.name}. I am ${this[age]-10}.`);
}
}
var j = new Person('Jane',45);
j.introduce(); // My name is Jane. I am 35.
console.log(JSON.stringify(j)); // {"name":"Jane"}
console.log(Object.keys(j)); // ["name"]
console.log(j[age]); // 45 (well…only if you know the age in the first place…)
객체 자체가 제공되지만 이러한 속성은 리플렉션, 프록시, Object.getOwnPropertySymbols () 등을 통해 여전히 노출 될 수 있지만 몇 가지 직접 메소드를 통해 액세스 할 수있는 자연스러운 방법은 없습니다. 때로는 OOP 관점에서 충분할 수도 있습니다.
답변
JS 심볼은 새로운 기본 데이터 유형입니다. 이것은 고유 한 ID 역할을하는 토큰입니다 . Symbol
생성자를 사용하여 심볼을 만들 수 있습니다 . 예를 들어 MDN의 다음 코드를 보자.
// The symbol constructor takes one optional argument,
// the descriptions which is used for debugging only.
// Here are two symbols with the same description
let Sym1 = Symbol("Sym");
let Sym2 = Symbol("Sym");
console.log(Sym1 == Sym2); // returns "false"
// Symbols are guaranteed to be unique.
// Even if we create many symbols with the same description,
// they are different values.
다음과 같이 심볼을 고유 한 객체 속성 키로 사용하는 것이 종종 편리합니다.
let obj = {};
let prop = Symbol();
obj[prop] = 123; // the symbol prop is assigned 123
obj.prop = 456; // the string prop is assigned 456
console.log(obj.prop, obj[prop]); // logs 456, 123
답변
기호에는 두 가지 주요 사용 사례가 있습니다.
“숨겨진”객체 속성. 다른 스크립트 나 라이브러리에 포함 된 객체에 속성을 추가하려는 경우 심볼을 만들어 속성 키로 사용할 수 있습니다. 기호 속성은에 표시되지 않으므로
for..in
실수로 다른 속성과 함께 처리되지 않습니다. 또한 다른 스크립트에는 심볼이 없으므로 직접 액세스 할 수 없습니다. 따라서이 속성은 실수로 사용하거나 덮어 쓰지 않도록 보호됩니다.그래서 우리는 상징적 인 속성을 사용하여 우리가 필요로하는 물체에 무언가를 숨기고 숨길 수 있습니다.
로 액세스 할 수있는 JavaScript에서 사용되는 많은 시스템 심볼이 있습니다
Symbol.*
. 우리는 그것들을 사용하여 내장 동작을 변경할 수 있습니다. 예를 들어, ….
Symbol.iterator
iterables의 경우Symbol.toPrimitive
객체 대 기본 변환 등을 설정합니다.