Simple to understand
Ecma-262 defines an object as an unordered collection of attributes. Simply put, it is data made up of multiple key-value pairs.
The “key” can be a string, a number, or a Symbol
Values can be basic types of data, array, map, set, {}, function(), etc
In JS, there is a saying that “everything is an object”, because most values can be represented by objects. Functions, arrays, object literals and so on are all objects in nature, including some primitive data types (such as String type), and JS also provides corresponding constructors.
Distinguishing concepts: objects (reference values), classes
An object is an instance of a particular reference type. In ECMAScript, reference types are structures that group data and functionality together.
While Javascript is technically an object-oriented language, ECMAScript lacks some of the basic constructs of traditional object-oriented programming languages, including classes and interfaces.
Reference types are sometimes called object definitions because they describe the properties and methods their objects should have
Reference types are a bit like classes, but they are not the same thing. The new class keyword introduced in ES6 has the ability to formally define classes, but it just encapsulates the syntactic sugar of constructor + stereotype inheritance
Simple understanding of objects
-
Create a new instance of Object
let obj = new Object(); obj.name = 'echo'; Copy the code
-
Use object literals
let obj = { name: 'echo' }; Copy the code
The above two actions of creating objects are equivalent
When you define an Object using an Object literal representation, the Object constructor is not actually called
-
Two ways to access properties in an object
-
Obj. name Common mode
-
Obj [‘name’] can be used to read the values of dynamic properties
-
A more complex object
let obj = {
name: 'echo',
friends: [
{
name: 'Jon',
age: 12
}
],
sayName() {
console.log(this.name);
}
}
obj.foo = Symbol('foo');
console.log(obj);
Copy the code
Traverse object
-
The for – not commonly used in
Returns all (enumerable and non-enumerable) properties on the instance and stereotype.
Note that the stereotype is not enumerable (
[[Enumerable]]
Property is set tofalse
The instance properties of the) property are also returned, since developer-defined properties are enumerable by default -
Object.getOwnPropertyNames(obj)
Lists all instance attributes, whether enumerable or not.
console.log(Object.getOwnPropertyNames(Person.prototype)); // ['constructor', 'name', 'age'] Copy the code
-
Object.getOwnPropertySymbols(obj)
ES6 added, and the Object. GetOwnPropertyNames (obj) are similar, just for Symbol type.
-
Object.keys(obj)
Returns all enumerable instance properties on the object (obj), the return value being a string array of enumerable property names
function Person() {} Person.prototype.name = 'echo'; Person.prototype.age = 12; let person1 = new Person(); person1.name = 'Jon'; console.log(Object.keys(person1)); // ['name'] Copy the code
Here are two new ES2017 methods for converting object content to a serialized — and more importantly, iterable — format
Note:
Non-string attributes are converted to string output
In addition, these two methods perform a shallow copy of the object
Properties of type Symbol are ignored
-
Object.values(obj)
ES2017 new, returns an array of property values
-
Object.entrues(obj)
New in ES2017, returns an array of key-value pairs
The internal properties of the property
Ecma-262 uses a number of internal features to describe the characteristics of attributes. These characteristics are defined by the specification for the Javascript implementation engine.
Therefore, developers cannot access these features directly in JS.
The specification uses [[]] to identify a feature as an internal feature, such as [[Enumerable]]
-
Data attributes
Data attributes have four properties that describe their behavior:
-
[[freely]] specifies whether it is Configurable. The default value is true
Indicates whether a property can be deleted and redefined by DELETE, whether its properties can be modified, and whether it can be changed to an accessor property.
-
[[Enumerable]] — Whether it can be iterated, default is true
Indicates whether a property can be returned through a for-in loop
-
[[Writable]] — Modifiable. Default is true
-
[Value]] — The actual Value of the attribute, which defaults to undefined
To modify the default properties of a property, you must use the object.defineProperty () method.
Two-way data binding in Vue is implemented using getter and setter + observer patterns for Object.defineProperty
let person = {}; Object.defineProperty(person, 'name', { writable: false, value: 'echo' }); console.log(person.name); // 'echo' person.name = 'Jon'; console.log(person.name); // 'echo' Copy the code
In the example above, when writable is set to false, the value of the name property cannot be changed.
Attempts to modify this property in non-strict mode are ignored, and in strict mode an error is thrown
Once a property is configured without any configurable information, it cannot be changed back to the configurable property. Calling Object.defineProperty() again and modifying any non-writable properties results in an error
In the call
Object.defineProperty()
When,configurable
,enumerable
andwritable
Is default if not specifiedfalse
. -
-
Accessor properties
Accessor properties do not contain data values. Instead, they contain two nonessential functions — getters and setters,
When an accessor property is read, the getter function is called to return the value of the property
When the accessor property is written, the setter function is called to set the latest value of the property
Accessor properties have four properties that describe their behavior:
-
[[freely]] — Specifies whether it is Configurable. The default is true
-
[[Enumerable]] — Whether you can erable, defaults to true
-
[[Get]] — Gets the function, called when the property is read. The default value is undefined
-
[[Set]] — Sets the function, called when writing properties. The default value is undefined
let person = { name_: 'echo', age: 1 } Object.defineProperty(person, 'name', { get() { return this.name_; }, set(newVal) { this.name_ = newVal; this.age ++; // A typical use of accessor properties is when setting a property value causes some other change to occur}}); person.name = 'Jon';Copy the code
Underlined properties are often used to indicate that the property is not intended to be accessed outside of object methods
Both get and set functions do not have to be defined.
Defining only the get function means that the property is read-only and attempts to modify the property are ignored. An error is thrown in strict mode.
Similarly, if there is only one set function property that cannot be read, reading in non-strict mode returns undefined, and in strict mode an error is thrown
-
-
Defining multiple properties
let person = {}; Object.defineProperties(person, { name_: { value: 'echo' }, age: { value: 1 }, name: { get() { return this.name_; }, set(newVal) { this.name_ = newVal; this.age++; }}})Copy the code
Read properties of properties
-
Object.getOwnPropertyDescriptor(obj, propertyName)
Gets the property descriptor for the specified property
/ / here in the language of the above person let descriptor = Object. GetOwnPropertyDescriptor (person, "name_"); console.log(descriptor.value); // 'echo' console.log(descriptor.configurable); // false console.log(typeof descriptor.get); // 'undefined', the result is 'function' console.log(descriptor. Enumerable); // falseCopy the code
-
Object. GetOwnPropertyDescriptors () ES2017 new static methods
This method will actually call Object on each has its own properties. The getOwnPropertyDescriptor () and return them in a new Object
console.log(Object.getOwnPropertyDescriptors(person)); // { // age: { // configurable: false, // enumerable: false, // value: 1, // writable: false // }, // name: { // configurable: false, // enumerable: false, // get: f(), // set: f(newVal), // }, // name_: { // configurable: false, // enumerable: false, // value: 'echo', // writable: false // } // } Copy the code
Object instances have the following properties and methods
-
obj.constructor
The function used to create the current object
-
obj.hasOwnPropety(name)
Used to determine whether a given attribute exists on the current object instance without checking its prototype
-
obj.isPrototypeOf(obj)
Used to determine whether the current object is a prototype of another object
-
obj.propertyIsEnumerable(name)
Used to determine whether a given property is enumerable
-
obj.toLocaleString()
Returns a string representation of an object
-
obj.toString()
Returns a string representation of an object
-
obj.valueOf()
Returns a string, numeric, or Boolean representation of an object.
Usually the same as the return value of toString()
Object Deconstruction (new in ES6)
Object deconstruction is the implementation of object attribute assignment using the structure matching the object.
const person = { name: 'echo', age: 12 } let {name, age} = person; console.log(name); // 'echo' console.log(age); // 12 let {name: pName, age: pAge} = person; console.log(pName); // 'echo' console.log(pAge); / / 12Copy the code
Destruct assignments do not necessarily match the attributes of the object, some attributes can be ignored when assigning, and the variable value is undefined if the referenced attribute does not exist
let {name, like} = person;
console.log(name); // 'echo'
console.log(like); // undefined
Copy the code
Define default values while deconstructing assignments
let {name, job = 'engineer'} = person;
Copy the code
If you are assigning to a previously declared variable, the assignment expression must be enclosed in a pair of parentheses
let pName, pAge;
let person = {
name: 'echo',
age: 12
};
({name: pName, age: pAge} = person);
console.log(pName, pAge); // echo 12
Copy the code
If a deconstructed expression involves multiple assignments and the initial assignment succeeds and the subsequent assignment fails, only part of the deconstructed assignment will be completed.
Destructuring assignments can also be done in function argument lists
let person = {
name: 'echo',
age: 12
};
function printPerson(foo, {name, age}, bar) {
console.log(arguments);
console.log(name, age);
}
printPerson('a', person, 2);
// ['a', {name: 'echo', age: 12}, 2]
// 'echo', 12
Copy the code
Optional chain operator
obj? The.name optional chain operator is a new feature included in the ECMAScript standard in December 2019.
If the object’s value is undefined or NULL when attempting to access an object’s property, the property access will generate an error. In order to improve the robustness of the program, it is usually necessary to check whether the object is initialized when accessing its properties. Only when the object is not undefined or NULL should the properties of the object be accessed.
The optional chain operator is designed to help developers eliminate tedious undefined and NULL checking code and enhance the expressivity of code.
-
Optional static property access to obj? .name
-
Optionally calculate property access to obj? [expr]
-
Optionally function call or method call fn? . ()
-
Short circuit is evaluated
&& and | | also has the characteristics of short circuit is evaluated
let x = 0; let a = undefined; a? .[++num]; console.log(x); / / 0Copy the code
Object equality judgment
Before ES6, there were some special cases where === was not distinguishable,
For example, console.log(+0 === -0); // true
To improve this situation, ES6 added object.is ()
console.log(Object.is(true, 1)); // false
console.log(Object.is({}, {})); // false
console.log(Object.is('2', 2)); // false
console.log(Object.is(+0, -0)); // false
console.log(Object.is(+0, 0)); // true
console.log(Object.is(NaN, NaN)); // true
Copy the code
To check for more than two values, recursively use equality passing:
function checkEqual(x, ... rest) { return Object,is(x, rest[0]) && (rest.length < 2 || checkEqual(... rest)); }Copy the code
Merge objects. assign(target, Origin [, origin1, origin2… )
Extension: shallow copy & deep copy
Copy all the local properties of the source object to the target object. This operation is sometimes referred to as mixin, because the target object is enhanced by mixing in the properties of the source object
let obj = Object.assign({ name: 'echo' }, { age: 12 })
Object.assign
If you modify the target object, the modified target object is also returned
const a = { name: 'echo' };
const c = Object.assign(a, {age: 12});
console.log(a); // {name: 'echo', age: 12}
console.log(c); // {name: 'echo', age: 12}
console.log(a === c); // true
Copy the code
-
For each qualifying attribute, the method uses [[Get]] on the source object to Get the value of the attribute, and then uses [[Set]] on the target object to Set the value of the attribute. Therefore, it assigns attributes, rather than just copying or defining new attributes. If the merge source contains getters, this may make it unsuitable to merge the new properties into the stereotype.
dest = { set a(val) { console.log(`Invoked dest setter with param ${val}`); }}; src = { get a() { console.log('Invoked src getter'); return 'foo'; }}; Object.assign(dest, src); console.log(dest);Copy the code
Parse the above code:
Call SRC get()
2. Call dest set() with the argument foo
3. Because the setup function here does not perform assignment
4. So there is no actual transfer of values
-
Each source Object can be enumerated in the (Object. PropertyIsEnumerable () returns true) and has its own attributes are copied to the target Object. If the attribute is duplicated, the subsequent attribute overrides the previous attribute value. Inherited properties and non-enumerable properties cannot be copied
Const obj = object. create({foo: 1}, {// foo is an inheritable property bar: {value: 2 // bar is an enumerable property}, baz: {value: 3, enumerable: True // baz is a self-enumerable property}}); const res = Object.assign({}, obj); console.log(res); // {baz: 3}Copy the code
-
Object.assign() executes a shallow copy of each source Object. For example:
const dest = {
a: 'a',
obj: {
b: 1
}
};
let origin = {
d: 66,
f: {
age: 12
}
};
const res = Object.assign(dest, origin);
origin.d = 1;
console.log('res1', origin, res);
Copy the code
Modify deep attribute values:
origin.f.age = 2;
console.log('res2', origin, res);
Copy the code
- Primitive types are wrapped as objects,
null
和undefined
Will be ignoredconst v1 = 'abc'; const v2 = true; const v3 = 10; const v4 = Symbol('foo'); const obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // Only string wrapping objects can have their own enumerable property console.log(obj); // { "0": "a", "1": "b", "2": "c" }Copy the code
- Cannot be rolled back. If an error occurs during assignment, the operation terminates and exits, with an error thrown. At this point, only partial replication may be completed
The advanced
Creating complex objects