이 기사의 내용은 JavaScript에서 Symbol 유형의 사용법에 관한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
Symbols는 ES6에 도입된 새로운 데이터 유형으로, 특히 객체 속성과 관련하여 JS에 몇 가지 이점을 제공합니다. 하지만 문자열은 할 수 없지만 기호는 무엇을 할 수 있나요?
기호에 대해 자세히 알아보기 전에 많은 개발자가 인식하지 못할 수 있는 몇 가지 JavaScript 기능을 살펴보겠습니다.
Background
js의 데이터 유형은 일반적으로 값 유형과 참조 유형의 두 가지 유형으로 나뉩니다.
값 유형(기본 유형): 숫자 유형(Number), 문자 유형(String), 부울 값 유형( 부울), null 및 불완전 참조 유형(클래스): 함수, 객체, 배열 등
값 유형 이해: 변수 간의 상호 할당은 새로운 메모리 공간을 열고 저장을 위해 변수 값을 새 변수에 할당하는 것을 의미합니다. 새로 열린 메모리에 두 변수의 후속 값 변경은 서로 영향을 미치지 않습니다. 예:
var a=10; //开辟一块内存空间保存变量a的值“10”; var b=a; //给变量 b 开辟一块新的内存空间,将 a 的值 “10” 赋值一份保存到新的内存里; //a 和 b 的值以后无论如何变化,都不会影响到对方的值;
C와 같은 일부 언어에는 참조 전달 및 값 전달 개념이 있습니다. JavaScript에는 전달된 데이터 유형을 기반으로 추론되는 비슷한 개념이 있습니다. 값이 함수에 전달되는 경우 값을 다시 할당해도 호출 위치의 값은 수정되지 않습니다. 그러나 참조 유형을 수정하면 수정된 값도 호출되는 위치에서 수정됩니다.
참조 유형 이해: 변수 간의 상호 할당은 개체(일반 개체, 함수 개체, 배열 개체)의 복사본을 새 변수에 복사하는 것이 아니라 포인터를 교환하는 것뿐입니다. , 단지 여러 개가 가이드를 제공합니다~~; 예:
var a={x:1,y:2} //需要开辟内存空间保存对象,变量 a 的值是一个地址,这个地址指向保存对象的空间; var b=a; // 将a 的指引地址赋值给 b,而并非复制一给对象且新开一块内存空间来保存; // 这个时候通过 a 来修改对象的属性,则通过 b 来查看属性时对象属性已经发生改变;
값 유형(신비한 NaN 값 제외)은 다음과 같이 항상 동일한 값을 가진 다른 값 유형과 정확히 동일합니다.
const first = "abc" + "def"; const second = "ab" + "cd" + "ef"; console.log(first === second); // true
그러나 참조 유형은 다음과 같습니다. 동일한 구조는 다음과 같지 않습니다.
const obj1 = { name: "Intrinsic" }; const obj2 = { name: "Intrinsic" }; console.log(obj1 === obj2); // false // 但是,它们的 .name 属性是基本类型: console.log(obj1.name === obj2.name); // true
객체는 JavaScript 언어에서 중요한 역할을 하며 어디에서나 사용됩니다. 객체는 키/값 쌍의 모음으로 사용되는 경우가 많지만 이런 방식으로 사용하는 데에는 큰 제한이 있습니다. symbol이 등장하기 전에는 객체 키는 문자열만 가능했고, 문자열이 아닌 것을 사용하려고 하면 값을 객체 키로 사용하면 값은 다음과 같이 문자열로 캐스팅됩니다.
const obj = {}; obj.foo = 'foo'; obj['bar'] = 'bar'; obj[2] = 2; obj[{}] = 'someobj'; console.log(obj); // { '2': 2, foo: 'foo', bar: 'bar', '[object Object]': 'someobj' }
What is Symbol
Symbol() 이 함수는 정적 속성과 정적 메서드가 있는 기호 유형의 값을 반환합니다. . 정적 속성은 여러 내장 멤버 개체를 노출합니다. 정적 메서드는 전역 기호 등록을 노출하고 내장 개체 클래스와 유사하지만 생성자로서 다음 구문을 지원하지 않기 때문에 완전하지 않습니다. >"새 기호()". 따라서 Symbol을 사용하여 생성된 값은 동일하지 않습니다. "new Symbol()"
。所以使用 Symbol 生成的值是不相等:
const s1 = Symbol(); const s2 = Symbol(); console.log(s1 === s2); // false
实例化 symbol 时,有一个可选的第一个参数,你可以选择为其提供字符串。 此值旨在用于调试代码,否则它不会真正影响symbol 本身。
const s1 = Symbol('debug'); const str = 'debug'; const s2 = Symbol('xxyy'); console.log(s1 === str); // false console.log(s1 === s2); // false console.log(s1); // Symbol(debug)
symbol 作为对象属性
symbol 还有另一个重要的用途,它们可以用作对象中的键,如下:
const obj = {}; const sym = Symbol(); obj[sym] = 'foo'; obj.bar = 'bar'; console.log(obj); // { bar: 'bar' } console.log(sym in obj); // true console.log(obj[sym]); // foo console.log(Object.keys(obj)); // ['bar']
乍一看,这看起来就像可以使用 symbol 在对象上创建私有属性,许多其他编程语言在其类中有自己的私有属性,私有属性遗漏一直被视为 JavaScript 的缺点。
不幸的是,与该对象交互的代码仍然可以访问其键为 symbol 的属性。 在调用代码尚不能访问 symbol 本身的情况下,这甚至是可能的。 例如,Reflect.ownKeys()
方法能够获取对象上所有键的列表,包括字符串和 symbol :
function tryToAddPrivate(o) { o[Symbol('Pseudo Private')] = 42; } const obj = { prop: 'hello' }; tryToAddPrivate(obj); console.log(Reflect.ownKeys(obj)); // [ 'prop', Symbol(Pseudo Private) ] console.log(obj[Reflect.ownKeys(obj)[1]]); // 42
注意:目前正在做一些工作来处理在JavaScript中向类添加私有属性的问题。这个特性的名称被称为私有字段,虽然这不会使所有对象受益,但会使类实例的对象受益。私有字段从 Chrome 74开始可用。
防止属性名称冲突
符号可能不会直接受益于JavaScript为对象提供私有属性。然而,他们是有益的另一个原因。当不同的库希望向对象添加属性而不存在名称冲突的风险时,它们非常有用。
Symbol 为 JavaScrit 对象提供私有属性还有点困难,但 Symbol 还有别外一个好处,就是避免当不同的库向对象添加属性存在命名冲突的风险。
考虑这样一种情况:两个不同的库想要向一个对象添加基本数据,可能它们都想在对象上设置某种标识符。通过简单地使用 id
function lib1tag(obj) { obj.id = 42; } function lib2tag(obj) { obj.id = 369; }
symbol
을 인스턴스화할 때 선택적으로 문자열을 제공할 수 있는 선택적 첫 번째 인수가 있습니다. 이 값은 코드 디버깅에 사용하기 위한 것입니다. 그렇지 않으면symbol
자체에 실제로 영향을 미치지 않습니다.const library1property = Symbol('lib1'); function lib1tag(obj) { obj[library1property] = 42; } const library2property = Symbol('lib2'); function lib2tag(obj) { obj[library2property] = 369; }symbol을 개체 속성으로 사용 🎜🎜symbol에는 또 다른 중요한 용도가 있습니다. 다음과 같이 개체의 키로 사용할 수 있습니다. 🎜
const library1property = uuid(); // random approach function lib1tag(obj) { obj[library1property] = 42; } const library2property = 'LIB2-NAMESPACE-id'; // namespaced approach function lib2tag(obj) { obj[library2property] = 369; }🎜얼핏 보면 🎜symbol🎜 개인 속성을 사용하여 개체에 생성할 수 있는 것처럼 보입니다. 다른 많은 프로그래밍 언어는 클래스에 자체적인 개인 속성을 가지고 있습니다. 개인 속성의 생략은 항상 JavaScript의 단점으로 간주되어 왔습니다. 🎜🎜안타깝게도 객체와 상호 작용하는 코드는 키가 기호인 객체 속성에 계속 액세스할 수 있습니다. 이는 호출 코드가 아직 기호 자체에 액세스할 수 없는 경우에도 가능합니다. 예를 들어
Reflect.ownKeys()
메서드는 문자열과 기호를 포함하여 객체의 모든 키 목록을 가져올 수 있습니다. 🎜const library2property = 'LIB2-NAMESPACE-id'; // namespaced function lib2tag(obj) { obj[library2property] = 369; } const user = { name: 'Thomas Hunter II', age: 32 }; lib2tag(user); JSON.stringify(user); // '{"name":"Thomas Hunter II","age":32,"LIB2-NAMESPACE-id":369}'
참고: 현재 추가 작업을 처리하기 위해 일부 작업이 진행 중입니다. 개인 속성과 관련된 JavaScript 문제의 클래스. 이 기능의 이름은 Private Fields라고 하며 이것이 모든 개체에 도움이 되는 것은 아니지만 클래스의 인스턴스인 개체에 도움이 됩니다. 비공개 필드는 Chrome 74부터 사용할 수 있습니다.🎜속성 이름 충돌 방지 🎜🎜 기호는 객체에 개인 속성을 제공하는 JavaScript로부터 직접적인 이점을 얻지 못할 수 있습니다. 하지만 이것이 유익한 이유는 또 있습니다. 이는 여러 라이브러리에서 이름 충돌 위험 없이 객체에 속성을 추가하려는 경우에 유용합니다. 🎜🎜Symbol JavaScript 개체에 개인 속성을 제공하는 것은 약간 어렵지만 Symbol에는 다른 라이브러리가 개체에 속성을 추가할 때 이름 지정 충돌의 위험을 피할 수 있다는 또 다른 장점이 있습니다. 🎜🎜두 개의 서로 다른 라이브러리가 객체에 기본 데이터를 추가하려는 상황을 생각해 보세요. 둘 다 객체에 일종의 식별자를 설정하려고 할 수도 있습니다. 단순히
id
를 키로 사용하면 여러 라이브러리가 동일한 키를 사용할 위험이 큽니다. 🎜const library2property = 'f468c902-26ed-4b2e-81d6-5775ae7eec5d'; // namespaced approach function lib2tag(obj) { Object.defineProperty(obj, library2property, { enumerable: false, value: 369 }); } const user = { name: 'Thomas Hunter II', age: 32 }; lib2tag(user); console.log(user); // {name: "Thomas Hunter II", age: 32, f468c902-26ed-4b2e-81d6-5775ae7eec5d: 369} console.log(JSON.stringify(user)); // {"name":"Thomas Hunter II","age":32} console.log(user[library2property]); // 369🎜기호를 사용하면 각 라이브러리는 인스턴스화 시 필요한 기호를 생성할 수 있습니다. 그런 다음 생성된 Symbol의 값을 개체의 속성으로 사용합니다. 🎜
const obj = {}; obj[Symbol()] = 1; Object.defineProperty(obj, 'foo', { enumberable: false, value: 2 }); console.log(Object.keys(obj)); // [] console.log(Reflect.ownKeys(obj)); // [ 'foo', Symbol() ] console.log(JSON.stringify(obj)); // {}🎜 이러한 이유로 Symbol은 JavaScript에 유익한 것 같습니다. 🎜🎜하지만 각 라이브러리가 인스턴스화될 때 단순히 임의의 문자열을 생성하거나 네임스페이스를 사용할 수 없는 이유는 무엇입니까? 🎜
const library1property = uuid(); // random approach function lib1tag(obj) { obj[library1property] = 42; } const library2property = 'LIB2-NAMESPACE-id'; // namespaced approach function lib2tag(obj) { obj[library2property] = 369; }
这种方法是没错的,这种方法实际上与 Symbol 的方法非常相似,除非两个库选择使用相同的属性名,否则不会有冲突的风险。
在这一点上,聪明的读者会指出,这两种方法并不完全相同。我们使用唯一名称的属性名仍然有一个缺点:它们的键非常容易找到,特别是当运行代码来迭代键或序列化对象时。考虑下面的例子:
const library2property = 'LIB2-NAMESPACE-id'; // namespaced function lib2tag(obj) { obj[library2property] = 369; } const user = { name: 'Thomas Hunter II', age: 32 }; lib2tag(user); JSON.stringify(user); // '{"name":"Thomas Hunter II","age":32,"LIB2-NAMESPACE-id":369}'
如果我们为对象的属性名使用了 Symbol,那么 JSON 输出将不包含它的值。这是为什么呢? 虽然 JavaScript 获得了对 Symbol 的支持,但这并不意味着 JSON 规范已经改变! JSON 只允许字符串作为键,JavaScript 不会尝试在最终 JSON 有效负载中表示 Symbol 属性。
const library2property = 'f468c902-26ed-4b2e-81d6-5775ae7eec5d'; // namespaced approach function lib2tag(obj) { Object.defineProperty(obj, library2property, { enumerable: false, value: 369 }); } const user = { name: 'Thomas Hunter II', age: 32 }; lib2tag(user); console.log(user); // {name: "Thomas Hunter II", age: 32, f468c902-26ed-4b2e-81d6-5775ae7eec5d: 369} console.log(JSON.stringify(user)); // {"name":"Thomas Hunter II","age":32} console.log(user[library2property]); // 369
通过将 enumerable
属性设置为 false
而“隐藏”的字符串键的行为非常类似于 Symbol 键。它们通过 Object.keys()
遍历也看不到,但可以通过 Reflect.ownKeys()
显示,如下的示例所示:
const obj = {}; obj[Symbol()] = 1; Object.defineProperty(obj, 'foo', { enumberable: false, value: 2 }); console.log(Object.keys(obj)); // [] console.log(Reflect.ownKeys(obj)); // [ 'foo', Symbol() ] console.log(JSON.stringify(obj)); // {}
在这点上,我们几乎重新创建了 Symbol。隐藏的字符串属性和 Symbol 都对序列化器隐藏。这两个属性都可以使用Reflect.ownKeys()方法读取,因此它们实际上不是私有的。假设我们为属性名的字符串版本使用某种名称空间/随机值,那么我们就消除了多个库意外发生名称冲突的风险。
但是,仍然有一个微小的区别。由于字符串是不可变的,而且 Symbol 总是保证惟一的,所以仍然有可能生成字符串组合会产生冲突。从数学上讲,这意味着 Symbol 确实提供了我们无法从字符串中得到的好处。
在 Node.js 中,检查对象时(例如使用 console.log() ),如果遇到名为 inspect 的对象上的方法,将调用该函数,并将打印内容。可以想象,这种行为并不是每个人都期望的,通常命名为 inspect 的方法经常与用户创建的对象发生冲突。
现在 Symbol 可用来实现这个功能,并且可以在 equire('util').inspect.custom 中使用。inspect 方法在Node.js v10 中被废弃,在 v1 1中完全被忽略, 现在没有人会偶然改变检查的行为。
模拟私有属性
这里有一个有趣的方法,我们可以用来模拟对象上的私有属性。这种方法将利用另一个 JavaScript 特性: proxy(代理)。代理本质上封装了一个对象,并允许我们对与该对象的各种操作进行干预。
代理提供了许多方法来拦截在对象上执行的操作。我们可以使用代理来说明我们的对象上可用的属性,在这种情况下,我们将制作一个隐藏我们两个已知隐藏属性的代理,一个是字符串 _favColor,另一个是分配给 favBook 的 S ymbol :
let proxy; { const favBook = Symbol('fav book'); const obj = { name: 'Thomas Hunter II', age: 32, _favColor: 'blue', [favBook]: 'Metro 2033', [Symbol('visible')]: 'foo' }; const handler = { ownKeys: (target) => { const reportedKeys = []; const actualKeys = Reflect.ownKeys(target); for (const key of actualKeys) { if (key === favBook || key === '_favColor') { continue; } reportedKeys.push(key); } return reportedKeys; } }; proxy = new Proxy(obj, handler); } console.log(Object.keys(proxy)); // [ 'name', 'age' ] console.log(Reflect.ownKeys(proxy)); // [ 'name', 'age', Symbol(visible) ] console.log(Object.getOwnPropertyNames(proxy)); // [ 'name', 'age' ] console.log(Object.getOwnPropertySymbols(proxy)); // [Symbol(visible)] console.log(proxy._favColor); // 'blue'
使用 _favColor 字符串很简单:只需阅读库的源代码即可。 另外,通过蛮力找到动态键(例如前面的 uuid 示例)。但是,如果没有对 Symbol 的直接引用,任何人都不能 从proxy 对象访问'Metro 2033'值。
Node.js警告:Node.js中有一个功能会破坏代理的隐私。 JavaScript语 言本身不存在此功能,并且不适用于其他情况,例 如Web 浏览器。 它允许在给定代理时获得对底层对象的访问权。 以下是使用此功能打破上述私有属性示例的示例:
const [originalObject] = process .binding('util') .getProxyDetails(proxy); const allKeys = Reflect.ownKeys(originalObject); console.log(allKeys[3]); // Symbol(fav book)
现在,我们需要修改全局 Reflect 对象,或者修改 util 流程绑定,以防止它们在特定的 Node.js 实例中使用。但这是一个可怕的兔子洞。
本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript教程视频栏目!
위 내용은 JavaScript에서 Symbol 유형의 용도는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

JavaScript는 현대 웹 개발의 핵심 언어이며 다양성과 유연성에 널리 사용됩니다. 1) 프론트 엔드 개발 : DOM 운영 및 최신 프레임 워크 (예 : React, Vue.js, Angular)를 통해 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축합니다. 2) 서버 측 개발 : Node.js는 비 차단 I/O 모델을 사용하여 높은 동시성 및 실시간 응용 프로그램을 처리합니다. 3) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

Dreamweaver Mac版
시각적 웹 개발 도구

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.
