This is the 17th day of my participation in Gwen Challenge

preface

We know that JS object attribute classification many, some are constructor own, some are prototype chain, some are enumerable, some are immutable and so on, ES6 and add a Symbol type, let JS object attribute more rich, this article is to get JS object attributes.

Classification by source

  • Has its own properties
  • The prototype property

The IN operator checks all proprietary and stereotype properties on an object, including the Symbol value.

The hasOwnProperty method determines whether a property is the object’s own property, including the Symbol value.

let s1 = Symbol('s1');

function Fun() {
    this.innerValue = 'Own property';
    this[s1] = 'Symbol properties'
}
Fun.prototype.proValue = "Stereotype properties";

let obj = new Fun()

console.log('innerValue' in obj);
console.log('proValue' in obj);
console.log(s1 in obj);

console.log('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --');

console.log(obj.hasOwnProperty('innerValue'));
console.log(obj.hasOwnProperty(s1));
console.log(obj.hasOwnProperty('proValue'));


// Execution result
true
true
true
-----------------
true
true
false
Copy the code

Property enumeration

You can enumerate all enumerable proprietary and stereotype properties on an object (excluding Symbol values).

Keys only enumerates its own properties (not including Symbol values).

Object. GetOwnPropertyNames returns a specified Object all its attributes (including an enumeration attributes, but does not include Symbol value) of the array.

All Object. GetOwnPropertySymbols returns a specified Object Symbol value.

Reflects. ownKeys can return all properties of an object itself, including the Symbol property

function Fun() {
    this.innerValue = 'Own property';
}
Fun.prototype.proValue = "Stereotype properties";

let obj = new Fun();
Object.defineProperty(obj, 'noEnum', {
    value: 'Non-enumerable properties'
})
let s1 = Symbol('s1');
obj[s1] = 'symbol properties'

let forInArr = [];
for(let key in obj) {
    forInArr.push(key);
}

console.log(forInArr);
console.log(Object.keys(obj));
console.log(Object.getOwnPropertyNames(obj));
console.log(Reflect.ownKeys(obj))

// Execution result
[ 'innerValue'.'proValue' ]
[ 'innerValue' ]
["innerValue"."noEnum"]
["innerValue"."noEnum".Symbol(s1)]
Copy the code

Classification by function

  • Data attributes
  • Accessor properties

Data attributes

A data attribute contains a value, and the default behavior of the object’s internal method [[PUT]] is to create a data attribute. Characteristic attributes owned by data attributes:

[[Value]] Stores the Value of the attribute.

[[Writable]] stores a Boolean value indicating whether the property can be changed.

[[Enumerable]] stores a Boolean value that indicates whether the property is Enumerable.

[[64x]] Stores a Boolean value that controls the writability of metadata of a property. If false, the property cannot be deleted. Cannot change most of the properties of this property (except [[Value]] and [[Writable]] mutable); A data attribute cannot be redefined as an accessor attribute.

let obj = {
    //x,y are data attributes
    x: 1.y: 2
}
Copy the code

Accessor properties

Accessor properties do not contain values, but instead define a getter and setter function. Accessor properties have the following characteristic properties:

[[Get]] stores the getter function that is called when the value of the property is read. The return value of the function is the value of the property.

[[Set]] stores the setter function, which is called when assigning a value to the property. The function is called with an argument (the new value assigned).

[[Enumerable]] stores a Boolean value that indicates whether the property is Enumerable.

[[64x]] Stores a Boolean value that controls the writability of metadata of a property. If false, the property cannot be deleted. Cannot change most features of this property (except [[Value]] and [[Writable]]); A data attribute cannot be redefined as an accessor attribute.

let obj = {
    x:1.y:2.//z is the accessor attribute
    get z() {
        return 3;
    },
    set z(val) {
        return 3;
    }
}

obj.z = 5;
console.log(obj.z);  / / 3
Copy the code

Defining object properties

Default values for data attributes and accessor attributes when defining Object attributes using Object.defineProperty:

Character name The default value
[[Value]] undefined
[[Writable]] false
[[Get]] undefined
[[Set]] undefined
[[Enumerable]] false
[[Configurable]] false

The [[Enumerable]], [[Writable]] and [[Writable] features default to true, and [[Value]] is the specified Value

// Method 1:
let obj = {};
obj.val = 'xxxx';

// Method 2:
let obj = {
    val: 'xxxx'
}
Copy the code

Attribute descriptor

You can use property descriptors to return all properties of a property as an object

{
    value: 1.writable: true.enumerable: true.configurable: true
}
Copy the code

Functions that use property descriptors

1. Object.defineProperty(obj, propName, PropDesc)

2. Object.defineProperties(obj, propDescObj)

3. Object.create(proto, propDescObj)

4. Object. GetOwnPropertyDescriptor (obj, propName) / / returns the Object obj propName attributes of its own properties (integrated) the properties of the descriptor

5. Object.getOwnPropertyDescriptors(obj)

Object.freeze()

Object.freeze() creates a frozen Object. Once an object is frozen, no new attributes can be added to it; Cannot delete existing attributes; You cannot modify the properties of an existing property of the object (enumerable, configurable, writable, etc.). You cannot modify the value of an existing property.

The object.isfrozen () method is used to determine whether an Object isFrozen.

Object.seal()

Object.seal() seals an Object. Prevents new attributes from being added; Mark all existing attributes as unconfigurable; The current property can be changed if it was previously writable.

The object.issealed () method determines whether an Object isSealed.

Object.preventExtensions()

Object.preventextensions () makes an Object unextensible and never adds new properties. (An object is extended if new attributes can be added to it.) Once marked as unextensible, it cannot be made extensible again; Object.preventextensions () only prevents the addition of its own properties, its Object prototypes are not affected; Non-extensible object properties can still be deleted.

The object.isextensible () method is used to determine whether an Object isExtensible.

The Object. Freeze, Object. Seal, Object. PreventExtensions methods all return the original Object and do not create a copy.

Inheritance of characteristic attributes

Data attributes [[Writable]],[[Value]],[[Enumerable]] are inheritable. The accessor properties [[Get]],[[Set]][[Enumerable]] are inheritable.

// If writable is set to false, the child object cannot be modified
let obj1 = {
    name:'obj1'
}

let obj2 = {}
Object.setPrototypeOf(obj2, obj1);
console.log(obj2.name);    //obj1
console.log(Object.getOwnPropertyDescriptor(obj2, 'name'));  //undefined

Object.defineProperty(obj1, 'name', {writable: false
})
obj2.name = 'obj2'
console.log(obj2.name);  //obj1
Copy the code

[[signals]] is non-inherited

let test = {
    age:12
}

Object.defineProperty(test, 'name', {
    value: 'hie'.writable: true.configurable: false.enumerable: false
});

let test2 = Object.create(test);
test2.name = 'test2'
console.log("------- before deletion", test2.name);   //test2
delete test2.name         //true, the deletion succeeded
console.log('------ after deletion ', test2.name)    //hie

delete test.name         //false, cannot be deleted
Copy the code

Special cases in the global environment:

A = 1 and var a = 1

Cause: Globally, both a=1 and var a=1 add an attribute to the window object. The default of the former works without any additional information, and signals is true, so the delete freely works without any additional information. The default of the latter works without any additional information, and signals is false

Internal properties

There are some properties that are just for specification use, they are not directly accessible through Javascript (through specific functions), but they do exist, and these are called internal properties. The name of the inner property is special, surrounded by two brackets.

  • [[Prototype]]. Indicates the Prototype of the owning object. Starting with ES6, [[Prototype]] can be accessed via Object.getProtoTypeof and Object.setProtoTypeof, which is the equivalent of Javascript’s nonstandard but many browser implementations of __proto__