neste post do blog, nós damos uma olhada mais de perto em como a especificação ECMAScript vê objetos JavaScript. In particular, properties are not atomic in the spec, but composed of multiple attributes (think fields in a record). Mesmo o valor de uma propriedade de dados é armazenado em um atributo!
Table of contents:
- the structure of objects #
- slots internos #
- teclas de Propriedade #
- os atributos de Propriedade #
- descritores de propriedade #
- recuperando descritores para propriedades #
- a Criação de novas propriedades através de descritores #
- Alterar propriedades existentes através de descritores #
- Armadilha: herdar propriedades só de leitura não podem ser atribuídas a #
- API: descritores de propriedade #
- casos de Uso para o Objeto.getOwnPropertyDescriptors () #
- Object.getOwnPropertyDescriptors(): copying properties into an object #
- Armadilha: copying methods that use super #
- Object.getownpropertydescriptors (): clonagem de objetos #
the structure of objects #
In The ECMAScript specification, an object consists of:
- slots internos, que são locais de armazenamento que não são acessíveis a partir de JavaScript, apenas para Operações na especificação.
- uma coleção de propriedades. Cada propriedade associa uma chave com atributos (pense campos em um registro).
slots internos #
Esta é a forma como a especificação descreve slots internos (a ênfase é minha):
- slots internos correspondem ao estado interno que está associado com objetos e usado por vários algoritmos de especificação ECMAScript.os slots internos não são propriedades de objetos e não são herdados.
- Dependendo específico ranhura interna especificação, tal estado pode consistir de valores:
- de qualquer tipo de linguagem ECMAScript ou
- específicos, ECMAScript especificação do tipo de valores.
- salvo indicação explícita em contrário, os slots internos são atribuídos como parte do processo de criação de um objecto e não podem ser adicionados dinamicamente a um objecto.
- salvo indicação em contrário, o valor inicial de um slot interno é o valor
undefined
. - vários algoritmos dentro desta especificação criam objetos que têm slots internos. No entanto, a linguagem ECMAScript não fornece nenhuma maneira direta de associar slots internos com um objeto.
- os métodos internos e as faixas horárias internas são identificados dentro desta especificação utilizando nomes entre parênteses rectos duplos
]
.
Existem dois tipos de slots internos:
- slots de método para manipular objetos (obter Propriedades, definir propriedades, etc.)
- Data slots with storage (listed in the table below)
Internal data slot | Type |
---|---|
] |
null | object |
] |
boolean |
] |
List of entries |
Descriptions for these data slots:
teclas de Propriedade #
A chave de uma propriedade é:
- Uma cadeia de caracteres
- Um símbolo
os atributos de Propriedade #
Existem dois tipos de propriedades e têm diferentes atributos:
- Uma propriedade de dados armazena os dados. Seus atributos
value
contém qualquer valor JavaScript. - uma propriedade de acessor tem uma função getter e / ou uma função setter. O primeiro é armazenado no atributo
get
, o segundo no atributoset
.
a tabela seguinte lista todos os atributos da propriedade.
Kind of property | Name and type of attribute | Default value |
---|---|---|
Data property | value: any |
undefined |
writable: boolean |
false |
|
Accessor property | get(): any |
undefined |
set(v: any): void |
undefined |
|
All properties | configurable: boolean |
false |
enumerable: boolean |
false |
We have already encountered the attributes value
get
, and set
. The other attributes work as follows:
-
writable
determina se o valor de uma propriedade de dados pode ser alterado. -
configurable
determina se os atributos de uma propriedade podem ser alterados. Se forfalse
, então:- Você não pode apagar a propriedade.
- Você não pode mudar uma propriedade de uma propriedade de dados para uma propriedade de acessor ou vice-versa.
- Não pode alterar nenhum atributo para além de
value
. - No entanto, é permitida mais uma alteração de atributos: Você pode alterar
writable
detrue
false
. A razão por trás desta anomalia é histórica: propriedade.length
de Arrays sempre foi escrita e não-configurável. Permitir que o seu atributowritable
seja alterado permite-nos congelar Arrays.
-
enumerable
influências de algumas operações (tais comoObject.assign()
). Se forfalse
, então essas operações ignoram a propriedade.
descritores de propriedade #
um descritor de propriedade codifica os atributos de uma propriedade como um objeto JavaScript. Suas interfaces TypeScript são as seguintes.os pontos de interrogação indicam que cada propriedade é facultativa. Se você omitir uma propriedade ao passar um descritor para uma operação, então o seu valor padrão é usado.
recuperando descritores para propriedades #
o seguinte código recupera o descritor do objecto para a propriedade de dados first
:
No próximo exemplo, vamos recuperar a propriedade descritor para o getter fullName
:
Usando a tag desc()
na linha de Um é um trabalho em torno de modo que .deepEqual()
funciona.
a Criação de novas propriedades através de descritores #
Você também pode criar novas propriedades através de descritores de propriedade:
Alterar propriedades existentes através de descritores #
Se uma propriedade já existe e, em seguida, definindo-a através de um descritor de alterações de propriedade. Por um lado, que nos permite usar Object.defineProperty()
como atribuição:
por outro lado, também podemos usar Object.defineProperty()
para ativar uma propriedade de dados em um getter (e vice-versa):
Armadilha: herdar propriedades só de leitura não podem ser atribuídas a #
Se uma herdou a propriedade é somente leitura, então não podemos usar de atribuição de alterá-lo. A lógica é que anular uma propriedade herdada através da criação de uma propriedade própria pode ser visto como uma mudança não destrutiva da propriedade herdada. Sem dúvida, se uma propriedade não é writável, não devemos ser capazes de fazer isso.vamos ver um exemplo.:não podemos mudar a propriedade por atribuição. Mas ainda podemos criar uma própria propriedade, definindo-o:
Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);
Acessor de propriedades que não têm um setter são também consideradas como somente leitura:
API: descritores de propriedade #
as funções A seguir permitem que você trabalhe com propriedade descritores:
casos de Uso para o Objeto.getOwnPropertyDescriptors () #
Object.getOwnPropertyDescriptors(): copying properties into an object #
Since ES6, JavaScript already had a tool method for copying properties: Object.assign()
. No entanto, este método utiliza simples de obter e definir as operações de cópia de uma propriedade cuja chave key
:
target = source;
Que significa que ele apenas cria uma cópia fiel de uma propriedade se:
- O atributo
writable
true
e o atributoenumerable
true
(porque é como atribuição cria propriedades).é uma propriedade de dados.
o exemplo seguinte ilustra esta limitação. Object source
has a setter whose key is data
.
Se a gente usar Object.assign()
copiar propriedade data
e, em seguida, o assessor de propriedade data
é convertido para uma propriedade de dados:
Felizmente, usando Object.getOwnPropertyDescriptors()
juntamente com Object.defineProperties()
não copiar fielmente a propriedade data
:
Armadilha: copying methods that use super
#
a method that uses super
is strongly connected with its home object (the object it is stored in). Não existe atualmente nenhuma maneira de copiar ou mover tal método para um objeto diferente.
Object.getownpropertydescriptors (): clonagem de objetos #
Clonagem superficial é semelhante às propriedades de cópia, razão pela qual Object.getOwnPropertyDescriptors()
é uma boa escolha aqui também.
para criar o clone, usamos Object.create()
: