JavaScript 객체 리터럴이 멋지다고 말하는 이유는 무엇입니까?
ECMAScript 2015 이전에는 JavaScript의 객체 리터럴(객체 이니셜라이저라고도 함) 기능이 매우 약했습니다. 다음 두 가지 속성만 정의할 수 있습니다.
공통 키/값 쌍 { name1: value }
Getters { get name(){..} } 및 setters { set name(val){..} }은 계산해야 하는 값을 설정하고 가져오는 데 사용됩니다.
안타깝게도 객체 리터럴의 모든 용도는 단 하나의 간단한 예에서 다룰 수 있습니다.
JS Bin에서 사용해 보세요
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
JavaScript는 프로토타입입니다. 언어 기반이므로 모든 것이 객체입니다. 언어는 객체 생성, 구조화 및 프로토타입 액세스와 관련하여 간단한 구조를 제공해야 합니다.
객체를 정의하고 프로토타입을 설정하는 것은 일반적인 작업입니다. 나는 항상 프로토타입 설정이 단일 구문을 사용하여 객체 리터럴로 직접 지원되어야 한다고 생각합니다.
안타깝게도 리터럴의 한계로 인해 직접적인 해결책이 없습니다. 객체 리터럴을 결합하고 프로토타입을 설정하려면 Object.create()를 사용해야 합니다.
JS Bin에서 사용해 보세요
var myProto = { propertyExists: function(name) { return name in this; } }; var myNumbers = Object.create(myProto); myNumbers['array'] = [1, 6, 7]; myNumbers.propertyExists('array'); // => true myNumbers.propertyExists('collection'); // => false
제 생각에는 이것이 불편한 해결책입니다. 자바스크립트는 프로토타입을 기반으로 하는데, 프로토타입에서 객체를 생성하는 것이 왜 이렇게 번거롭나요?
다행히도 JavaScript는 변화하고 있습니다. 더욱 실망스러운 많은 문제는 JavaScript를 통해 단계별로 해결되고 있습니다.
이 기사에서는 ES2015가 위의 문제를 해결하고 추가 이점을 위해 객체 리터럴을 개선하는 방법을 설명합니다.
객체 생성 중 프로토타입 설정
-
약식 메서드 정의
상위 클래스 메서드 호출
계산된 속성 이름
In 그동안 최신 제안(2단계)인 객체 나머지 속성과 속성 확장 연산자를 살펴보겠습니다.
1. 객체 생성 중에 프로토타입 설정
이미 알고 있듯이 기존 객체의 프로토타입에 액세스하는 방법 중 하나는 getter 속성 __proto__:
JS Bin에서 시도
var myObject = { name: 'Hello World!' }; myObject.__proto__; // => {} myObject.__proto__.isPrototypeOf(myObject); // => true
myObject.__proto__ myObject의 프로토타입 객체를 반환합니다.
좋은 소식은 ES2015에서는 객체 리터럴 { __proto__: protoObject }의 프로토타입을 설정하기 위해 리터럴 __proto__를 속성 이름으로 사용할 수 있다는 것입니다.
让我们用 __proto__ 重写一下上面那个例子,让它看起来好一点:
Try in JS Bin
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 对象使用原型 myProto 创建,这可以通过特殊属性 __proto__ 实现。
这个对象通过简单的语句创建,而不需要额外的函数例如 Object.create()。
如你所见,使用 __proto__ 是简单的。我偏爱简单直接的解决方案。
有点说跑题了,回到主题来。我认为获得简单和可靠的解决方案需要通过大量的设计和实践。如果一个解决方案是简单的,你可能认为它同样也很容易被设计出来,然而事实并不是这样:
让它变得简单明了的过程是复杂的
让它变得复杂和难以理解却很容易
如果某个东西看起来太复杂或者用起来不舒服,很可能它的设计者考虑不周。
元芳,你怎么看?(欢迎在文章底部发表评论参与讨论)
2.1 使用 __proto__ 的特例
尽管 __proto__ 看似简单,却有一些特殊的场景你需要格外注意。
在对象字面量中 __proto__ 只允许使用一次。多次使用的话 JavaScript 会抛出异常:
Try in JS Bin
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。
JavaScript 限制了只允许使用 object 或者 null 作为 __proto__ 属性的值。使用其它原生类型(如字符串、数值、布尔类型)或者 undefined 会被忽略,并不能改变对象的原型。
看一个例子:
Try in JS Bin
var objUndefined = { __proto__: undefined }; Object.getPrototypeOf(objUndefined); // => {} var objNumber = { __proto__: 15 }; Object.getPrototypeOf(objNumber); // => {}
上面的例子里,对象字面量使用 undefined 和数值 15 来设置 __proto__ 值。因为只有对象或者 null 才允许被使用,objUndefined 和 objNumber 仍然是它们默认的原型:简单 JavaScript 对象 {}。__proto__ 的赋值被忽略了。
当然,尝试使用原生类型来设置对象的原型,这本身是很奇怪的。所以在这里做限制是符合预期的。
2. 速记方法定义
现在对象字面量中可以使用一个更短的语法来声明方法,省略 function 关键字和冒号。这被叫做速记方法定义(shorthand method definition)。
让我们用新的方式来定义一些方法:
Try in JS Bin
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. 调用父类方法
一个有趣的改进是能够使用 super 关键字来访问从原型链继承下来的属性。看下面的例子:
Try in JS Bin
var calc = { sumArray (items) { return items.reduce(function(a, b) { return a + b; }); } }; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements() { return super.sumArray(this.numbers); } }; numbers.sumElements(); // => 17
calc 是 numbers 对象的属性。在 numbers 的方法 sumElements 里面,要调用原型 calc上的方法,可以使用 super 关键字: super.sumArray()。
所以 super 是从原型链访问被继承的属性的一个快捷的方法。
在上一个例子里,我们也可以直接调用 cale.sumArray(),不过 super 是一个更好的选择因为它访问对象的原型链。它的存在清晰地暗示了继承的属性将被使用。
3.1 使用 super 的限制
在对象字面量中, super 只能用在速记方法定义中。
如果在普通的方法声明 { name: function() {} } 中使用它,JavaScript 会抛异常:
Try in JS Bin
var calc = { sumArray (items) { return items.reduce(function(a, b) { return a + b; }); } }; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements: function() { return super.sumArray(this.numbers); } }; // Throws SyntaxError: 'super' keyword unexpected here numbers.sumElements();
上面的代码里,方法 sumElements 被定义为:sumElements:function(){...}。由于 super要求在速记方法中使用,在其中调用 super 将抛出异常:SyntaxError: 'super' keyword unexpected here。
这个限制不会对对象字面量声明有多少影响,因为大部分情况下我们没有理由不用速记方法定义,毕竟它语法更简单。
4. 计算属性名称
在 ES2015 之前,对象初始化器的属性名称是字面量,大多数情况下是静态字符串。要创建一个动态计算的属性名,你不得不使用属性访问器:
Try in JS Bin
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}。这个表达式计算结果将成为属性名。
我真的很喜欢这个语法:短而简单。
让我们改进上面的代码:
Try in JS Bin
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 来迭代遍历一个对象的自有属性名,代码如下:
Try in JS Bin
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. 展望未来:rest 和属性展开
对象字面量的 Rest 和属性展开 是新的标准草案中的一个提案(stage 2),意味着这一特性是新版本 JavaScript 的规范的候选。
数组的 展开和 rest 操作符 已经被实现了。
Rest 属性 允许我们从解构赋值左侧使用对象来收集属性,看下面的例子:
Try in JS Bin
var object = { propA: 1, propB: 2, propC: 3 }; let {propA, ...restObject} = object; propA; // => 1 restObject; // => { propB: 2, propC: 3 }
属性展开 允许将源对象的自有属性拷进对象字面量内部。在上面的例子中,对象字面量从 souce对象中收集额外的属性。
Try in JS Bin
var source = { propB: 2, propC: 3 }; var object = { propA: 1, ...source } object; // => { propA: 1, propB: 2, propC: 3 }
6. 结论
JavaScript 在快速进步。
即使是相对小的结构比如对象字面量在 ES2015 中都有相当大的改进,更别说还有一大堆新特性在草案中。
你可以从初始化器中使用 __proto__ 属性直接设置对象的原型,这比使用 Object.create() 要更方便。
方法声明可以写成更简短的形式,这样你就不用写 function 关键字了。然后在速记方法中可以使用 super 关键字,它能提供方便的对被继承原型链上属性的访问。
如果一个属性名在运行时计算,现在你可以使用计算属性名称 [表达式] 来初始化对象。
的确,对象字面量现在很酷!
你觉得呢?欢迎在下方发表评论参与讨论。
以上就是为什么我要说 JavaScript 对象字面量很酷的内容,更多相关内容请关注PHP中文网(www.php.cn)!

핫 AI 도구

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

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

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

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

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

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

PHP의 요청 객체는 클라이언트가 서버로 보낸 HTTP 요청을 처리하는 데 사용되는 객체입니다. Request 객체를 통해 요청 메소드, 요청 헤더 정보, 요청 매개변수 등과 같은 클라이언트의 요청 정보를 얻어 요청을 처리하고 응답할 수 있습니다. PHP에서는 $_REQUEST, $_GET, $_POST 등과 같은 전역 변수를 사용하여 요청된 정보를 얻을 수 있지만 이러한 변수는 객체가 아니라 배열입니다. 요청사항을 보다 유연하고 편리하게 처리하기 위해

MySQL 쿼리 결과 배열을 객체로 변환하는 방법은 다음과 같습니다. 빈 객체 배열을 만듭니다. 결과 배열을 반복하고 각 행에 대해 새 개체를 만듭니다. foreach 루프를 사용하여 각 행의 키-값 쌍을 새 개체의 해당 속성에 할당합니다. 개체 배열에 새 개체를 추가합니다. 데이터베이스 연결을 닫습니다.

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

PHP에서 배열은 순서가 지정된 시퀀스이며 요소는 인덱스로 액세스됩니다. 객체는 new 키워드를 통해 생성된 속성과 메서드가 있는 엔터티입니다. 배열 액세스는 인덱스를 통해 이루어지며, 객체 액세스는 속성/메서드를 통해 이루어집니다. 배열 값이 전달되고 객체 참조가 전달됩니다.

JavaScript에서 HTTP 상태 코드를 얻는 방법 소개: 프런트 엔드 개발에서 우리는 종종 백엔드 인터페이스와의 상호 작용을 처리해야 하며 HTTP 상태 코드는 매우 중요한 부분입니다. HTTP 상태 코드를 이해하고 얻는 것은 인터페이스에서 반환된 데이터를 더 잘 처리하는 데 도움이 됩니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. HTTP 상태 코드란 무엇입니까? HTTP 상태 코드는 브라우저가 서버에 요청을 시작할 때 서비스가

C++에서는 함수가 객체를 반환할 때 주의해야 할 세 가지 사항이 있습니다. 객체의 수명 주기는 메모리 누수를 방지하기 위해 호출자가 관리합니다. 매달린 포인터를 피하고 메모리를 동적으로 할당하거나 개체 자체를 반환하여 함수가 반환된 후에도 개체가 유효한지 확인하세요. 컴파일러는 성능을 향상시키기 위해 반환된 개체의 복사 생성을 최적화할 수 있지만 개체가 값 의미 체계에 따라 전달되는 경우 복사 생성이 필요하지 않습니다.
