이 기사에서는 JavaScript의 객체 리터럴을 이해하고 객체 리터럴이 멋진 이유를 분석하도록 안내합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
ECMAScript 2015 이전에는 Javascript의 객체 리터럴(객체 이니셜라이저라고도 함)은 두 가지 유형의 속성을 정의할 수 있었습니다.
- 정적 속성 이름과 값의 쌍
{ name1 : value1 }
- 通过 getters
{ get name(){..} }
和 setters{ set name(val){..} }
定义的动态计算属性值
{ name1: value1 }
说来遗憾,一个简单的例子就可以表示对象字面量的所有可能性:
var myObject = { myString: 'value 1', get myNumber() { return this._myNumber; }, set myNumber(value) { this._myNumber = Number(value); }, }; myObject.myString; // => 'value 1' myObject.myNumber = '15'; myObject.myNumber; // => 15
JS 是一种基于原型的语言,因此一切都是对象。 在对象创建,配置和访问原型时,必须提供一种易于构造的语言。
定义一个对象并设置它的原型是一个常见的任务。最好的方式是直接在对象字面量使用一条语句来设置原型。
不幸的是,字面量的局限性不允许用一个简单的解决方案来实现这一点。必须结合使用object.create()
和对象字面量来设置原型。
var myProto = { propertyExists: function(name) { return name in this; } }; var myNumbers = Object.create(myProto); myNumbers['arrat'] = [1, 6, 7]; myNumbers.propertyExists('array'); // => true myNumbers.propertyExists('collection'); // => false
我认为这种解决方案不够灵活。JS 是基于原型的,为什么要用原型创建对象那么麻烦?
幸运的是,JavaScript 也在慢慢完善。JS 中许多相当令人不舒服的特性正在一步步的被解决。
这篇文章演示了 ES2015 是如何解决以上描述的难题,并增加了哪些特性来提升对象字面量的能力:
- 在对象构造函数中设置原型
- 速写式方法声明
- 进行
super
调用 - 可计算的属性名
另外,还有我们可以展望一下将来,看看 (草案2) 里的新提议: 可收集可展开的属性。
1. 在对象构造函数中设置原型
正如你已知的,访问已创建对象的原型有一种方式是引用 __proto__
这个 getter 属性:
var myObject = { name: 'Hello World!', }; myObject.__proto__; // => {} myObject.__proto__.isPrototypeOf(myObject); // => true
myObject.__proto__
返回 myObject
的原型对象。
请注意,不建议将 object.__ proto__
用作 getter/setter
。替代方法应考虑使用Object.getPrototypeOf()
和 Object.setPrototypeOf()
。
好消息是, ES2015 允许使用 __proto__
在对象字面量 { __proto__: protoObject }
中作为属性名来设置原型。
让我们用 __proto__
属性为对象初始化,看它是如何改进介绍中描述的不直观方案:
var myProto = { propertyExists: function(name) { return name in this; }, }; var myNumbers = { __proto__: myProto, array: [1, 6, 7], }; myNumbers.propertyExists('array'); // => true myNumbers.propertyExists('collection'); // => false
myNumbers
是使用了特殊的属性名 __proto__
创建的对象,它的原型是 myProto
。这个对象用了一个简单的声明来创建,没有使用类似 Object.create()
的附加函数。
如你所见,使用 __proto__
进行编码很简单。我通常推荐简洁直观的解决方案。
说点一些题外话,我认为有点奇怪的是,简单可扩展的解决方案依赖大量的设计和工作。如果一个方案很简洁,你也许认为它是容易设计的。然而事实完全相反:
- 让事情变得简单直接很复杂
- 让事情变得复杂难以理解很容易
如果一些事情看起来很复杂或者很难使用,可能它是没有被充分考虑过。关于返璞归真,你怎么看?(随意留言评论)
1.1 特殊的情况下 __proto__
的使用手册
即使 __proto__
getters
{ get name(){..} }
및 setters🎜 { 세트 이름( val) {..} }
동적으로 계산된 속성 값 정의🎜죄송하지만 간단한 예는 객체 리터럴의 모든 가능성을 나타낼 수 있습니다.🎜var object = { __proto__: { toString: function() { return '[object Numbers]' } }, numbers: [1, 5, 89], __proto__: { toString: function() { return '[object ArrayOfNumbers]' } } };🎜JS는 프로토타입이므로 모든 것이 객체입니다. 객체 생성, 구성, 프로토타입 액세스를 위해 쉽게 구성할 수 있는 언어를 제공해야 합니다. 🎜🎜객체를 정의하고 프로토타입을 설정하는 것은 일반적인 작업입니다. 가장 좋은 방법은 명령문을 사용하여 객체 리터럴에 직접 프로토타입을 설정하는 것입니다. 🎜🎜안타깝게도 리터럴의 한계로 인해 이를 달성하기 위한 간단한 솔루션이 허용되지 않습니다. 프로토타입을 설정하려면 객체 리터럴과 함께
object.create()
를 사용해야 합니다. 🎜var objUndefined = { __proto__: undefined, }; Object.getPrototypeOf(objUndefined); // => {} var objNumber = { __proto__: 15, }; Object.getPrototypeOf(objNumber); // => {}🎜이 솔루션은 유연성이 부족하다고 생각합니다. JS는 프로토타입을 기반으로 하는데 프로토타입을 사용하여 객체를 만드는 것이 왜 그렇게 번거로운가요? 🎜🎜다행히 JavaScript도 서서히 발전하고 있어요. JS의 다소 불편한 기능 중 상당수가 단계별로 해결되고 있습니다. 🎜🎜이 기사에서는 ES2015가 위에서 설명한 문제를 해결하고 객체 리터럴의 기능을 향상시키는 기능을 추가하는 방법을 보여줍니다. 🎜🎜🎜객체 생성자에 프로토타입 설정🎜간단 메서드 선언 li>🎜Make
super
호출🎜계산 가능한 속성 이름🎜또한 미래를 내다볼 수 있습니다(Draft 2 🎜의 새로운 제안): 수집 및 확장 가능한 속성 . 🎜🎜
1. 객체 생성자에서 프로토타입을 설정하세요
🎜아시다시피 생성된 객체의 프로토타입에 액세스하는 한 가지 방법은 참조하는 것입니다.__proto__ 이 getter 속성: 🎜var collection = { items: [], add(item) { this.items.push(item); }, get(index) { return this.items[index]; }, }; collection.add(15); collection.add(3); collection.get(0); // => 15🎜
myObject.__proto__
myObject
의 프로토타입 객체를 반환합니다. 🎜🎜
getter/setter
로 object.__ proto__
를 사용하는 것은 권장되지 않습니다. Object.getPrototypeOf()
및 Object.setPrototypeOf()
를 사용하여 대안을 고려해야 합니다. 🎜🎜좋은 소식은 ES2015에서는 객체 리터럴 { __proto__: protoObject }
의 속성 이름으로 🎜 __proto__
사용을 허용합니다. > 프로토타입을 설정합니다. 🎜🎜 __proto__
속성으로 개체를 초기화하고 소개에서 설명한 비직관적인 솔루션이 어떻게 개선되는지 살펴보겠습니다. 🎜var calc = { numbers: null, sumElements() { return this.numbers.reduce(function(a, b) { return a + b; }); }, }; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements() { if (this.numbers == null || this.numbers.length === 0) { return 0; } return super.sumElements(); }, }; numbers.sumElements(); // => 17🎜
myNumbers
는 특수 속성 이름을 사용하고 있습니다.__proto__에 의해 생성된 프로토타입은 myProto
입니다. 이 객체는 Object.create()
와 같은 추가 함수를 사용하지 않고 간단한 선언만으로 생성됩니다. 🎜🎜보시다시피 __proto__
를 사용하여 코딩하는 것은 간단합니다. 저는 보통 간단하고 직관적인 솔루션을 추천합니다. 🎜🎜좀 더 이야기하자면, 단순하고 확장 가능한 솔루션이 많은 설계와 작업에 의존한다는 점이 좀 이상하다고 생각합니다. 솔루션이 간단하다면 디자인하기도 쉽다고 생각할 수도 있습니다. 하지만 사실은 그 반대입니다. 🎜🎜🎜일을 간단하고 간단하게 만드는 것은 쉽습니다🎜일을 복잡하고 이해하기 어렵게 만드는 것은 쉽습니다🎜뭔가 복잡하거나 어려워 보인다면 를 사용하려면 완전히 고려되지 않았을 수도 있습니다. 자연으로 돌아가는 것에 대해 어떻게 생각하시나요? (댓글을 남겨주세요) 🎜🎜1.1 특수 사례 __proto__
사용자 매뉴얼🎜🎜 __proto__
가 단순해 보이지만 몇 가지 특수한 경우가 있습니다. 주의를 기울일 필요가 있습니다. 🎜
对象字面量中 __proto__
只允许使用 一次 。重复使用 JS 会抛出异常:
var object = { __proto__: { toString: function() { return '[object Numbers]' } }, numbers: [1, 5, 89], __proto__: { toString: function() { return '[object ArrayOfNumbers]' } } };
上面示例中的对象字面量使用了两次 __proto__
属性,这是不允许的。在这种情况下,将在会抛出 SyntaxError: Duplicate __proto__ fields are not allowed in object literals
的语法错误。
JS 约束只能用一个对象或 null
作为 __proto__
属性值。任何使用原始类型(字符串,数字,布尔值)或 undefined
类型都将被忽略,并且不会更改对象的原型。
让我们看看这个限制的例子:
var objUndefined = { __proto__: undefined, }; Object.getPrototypeOf(objUndefined); // => {} var objNumber = { __proto__: 15, }; Object.getPrototypeOf(objNumber); // => {}
这个对象字面量使用了 undefined
和数字 15
来设置 __proto__
的值。因为只有对象或 null
允许被当做原型, objUndefined
和 objNumber
仍然拥有他们默认的原型: JavaScript 空对象 {}
。 __proto__
的值被忽略了。
当然,尝试用原始类型去设置对象的原型会挺奇怪。这里的约束符合预期。
2. 速写式方法声明
可以使用较短的语法在对象常量中声明方法,以省略 function
关键字和 :
冒号的方式。它被称之为速写式方法声明。
接着,让我们使用速写的方法来定义一些方法吧:
var collection = { items: [], add(item) { this.items.push(item); }, get(index) { return this.items[index]; }, }; collection.add(15); collection.add(3); collection.get(0); // => 15
add()
和 get()
是 collection
里使用这个缩写形式定义的方法。
这个方法声明的方式还一个好处是它们都是非匿名函数,这在调试的时候会很方便。 上个例子执行 collection.add.name
返回函数名 'add'
。
3. 进行 <span style="font-size: 18px;">super</span>
调用
JS 一个有趣的改进是可以使用 super
关键字来访问原型链中父类的属性。看下面的例子:
var calc = { numbers: null, sumElements() { return this.numbers.reduce(function(a, b) { return a + b; }); }, }; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements() { if (this.numbers == null || this.numbers.length === 0) { return 0; } return super.sumElements(); }, }; numbers.sumElements(); // => 17
calc
是 numbers
对象的原型。在 numbers
的 sumElements
方法中,可以通过 super
关键字调用原型的 super.sumArray()
方法。
最终, super
是从对象原型链访问继承的属性的快捷方式。
在前面的示例中,可以尝试直接执行 calc.sumElements()
来调用原型。 然而,super.sumElements()
可以正确调用,因为它访问对象的原型链。并确保原型中的 sumElements()
方法使用 this.numbers
正确访问数组。
super
存在清楚地表明继承的属性将被使用。
3.1 super
的使用限制
super
在对象字面量中 只能在速写式方法声明里 使用。
如果尝试从普通方法声明 { name: function() {} }
访问它,JS 将抛出一个错误:
var calc = { numbers: null, sumElements() { return this.numbers.reduce(function(a, b) { return a + b; }); }, }; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements: function() { if (this.numbers == null || this.numbers.length === 0) { return 0; } return super.sumElements(); }, }; // Throws SyntaxError: 'super' keyword unexpected here numbers.sumElements();
这个 sumElements
方法被定义为一个属性: sumElements: function() {...}
, 因为 super
只能在速写式方法声明中使用。所以,在这种情况下调用它会抛出 SyntaxError: 'super' keyword unexpected here
的语法错误。
此限制在很大程度上不影响对象字面量的声明方式。 多数情况下因为语法更简洁,使用速写式方法声明会更好。
4. 可计算的属性名
在 ES2015 之前, 对象初始化使用的是字面量的形式,通常是静态字符串。要创建具有计算名称的属性,就必须使用属性访问器。
function prefix(prefStr, name) { return prefStr + '_' + name; } var object = {}; object[prefix('number', 'pi')] = 3.14; object[prefix('bool', 'false')] = false; object; // => { number_pi: 3.14, bool_false: false }
当然,这种定义属性的方式到目前为止令人愉快。
计算属性名称可以很好地解决该问题。当你要通过某个表达式计算属性名时,在方括号 {[expression]: value}
里替换对应的代码。对应的表达式会把计算结果作为属性名。
我非常喜欢这个语法:简短又简洁。
让我们改进上面的例子:
function prefix(prefStr, name) { return prefStr + '_' + name; } var object = { [prefix('number', 'pi')]: 3.14, [prefix('bool', 'false')]: false, }; object; // => { number_pi: 3.14, bool_false: false }
[prefix('number', 'pi')]
通过计算 prefix('number', 'pi')
表达式设置了 'number_pi'
这个属性名。
相应地, [prefix('bool', 'false')]
将第二个属性名称设置为 'bool_false'
。
4.1 Symbol
作为属性名
Symbols 也可以作为可计算的属性名。只要确保将它们包括在方括号中即可: { [Symbol('name')]: 'Prop value' }
。
例如,让我们用 Symbol.iterator
这个特殊的属性,去遍历对象的自有属性名。如下所示:
var object = { number1: 14, number2: 15, string1: 'hello', string2: 'world', [Symbol.iterator]: function *() { var own = Object.getOwnPropertyNames(this), prop; while(prop = own.pop()) { yield prop; } } } [...object]; // => ['number1', 'number2', 'string1', 'string2']
[Symbol.iterator]: function *() { }
定义一个属性,该属性用于迭代对象的自有属性。展开操作符 [...object]
使用了迭代器来返回自有属性的数组。
5. 对未来的一个展望: 可收集可展开的属性
对象字面量的可收集可展开的属性 目前是草案第二阶段 (stage 2) 中的一个提议,它将被选入下一个 Javascript 版本。
它们等价于 ECMAScript 2015 中已可用于数组的 展开和收集操作符 。
可收集的属性 允许收集一个对象在解构赋值后剩下的属性们。
下面这个例子收集了 object
解构后留下的属性:
var object = { propA: 1, propB: 2, propC: 3, }; let { propA, ...restObject } = object; propA; // => 1 restObject; // => { propB: 2, propC: 3 }
可展开的属性 允许从一个源对象拷贝它的自有属性到另一个对象字面量中。这个例子中对象字面量的其它属性合集是从 source
对象中展开的:
var source = { propB: 2, propC: 3, }; var object = { propA: 1, ...source, }; object; // => { propA: 1, propB: 2, propC: 3 }
6. 总结
JavaScript 正在迈出重要的一步。
在ECMAScript 2015中,即使是作为对象字面量的相对较小的结构也得到了相当大的改进。提案草案中还包含了许多新功能。
你可以在对象初始化时直接通过 __proto__
属性名设置其原型。比用 Object.create()
简单很多。
请注意,__proto__
是 ES2015 标准附件B的一部分,不鼓励使用。 该附件实现对于浏览器是必需的,但对于其他环境是可选的。NodeJS 4、5和6支持此功能。
现在方法声明有个更简洁的模式,所以你不必输入 function
关键字。而且在速写式声明里,你可以使用 super
关键字,它允许你十分容易得通过对象的原型链访问父类属性。
如果属性名需要在运行时计算,现在你可以用可计算的属性名 [expression]
来初始化对象。
对象字面量现在确实很酷!
英文原文地址:https://dmitripavlutin.com/why-object-literals-in-javascript-are-cool/
作者:Dmitri Pavlutin
译文地址:https://segmentfault.com/a/1190000020669949
更多编程相关知识,请访问:编程视频!!
위 내용은 JavaScript의 객체 리터럴에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.


핫 AI 도구

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

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

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

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경
