object

A plain object, or just an object.

literal

let user = new Object(a);// Constructor syntax
let user = {};  // The syntax for "literal"
Copy the code

Text and attributes

An object property consists of a key value

let user = {     // An object
  name: "John".// key "name", value "John"
  age: 30        // key "age", value 30
};
Copy the code

Properties can be deleted by delete

delete user.age;
Copy the code

The square brackets

To access attributes

let user = {};
user["likes birds"] = true;
alert(user["likes birds"]); // true
Copy the code

Dot notation

let user = {};
user["likes"] = true;
alert(user.likes); // true
Copy the code

Calculate attribute

let fruit = prompt("Which fruit to buy?"."apple");
let bag = {
  [fruit]: 5.// The attribute name is derived from the fruit variable
};
alert( bag.apple ); // 5 如果 fruit="apple"
Copy the code

// Attributes are not fixed, but randomly specified.

let fruit = prompt("Which fruit to buy?"."apple");
let bag = {};
// Get the value from the fruit variable
bag[fruit] = 5;
Copy the code

Short for property value

function makeUser(name, age) {
  return {
    name: name,
    age: age,
  };
}
Copy the code

Abbreviated as

function makeUser(name, age) {
  return {
    name, // Same as name: name
    age,  // Same as age: age
  };
}
Copy the code

Attribute name restriction

Object properties are not affected by system reserved keywords.

// These attributes are ok
let obj = {
  for: 1.let: 2.return: 3
};
alert( obj.for + obj.let + obj.return );  / / 6
Copy the code

Even if the variable is int 0, the system will automatically convert it to “0”

let obj = {
  0: "test" // equivalent to "0": "test"
};
alert( obj["0"]);// test
alert( obj[0]);// test (same property)
obj. 0 // This will fail
Copy the code

Attribute presence judgment

  1. Direct judgment undefined
   let user = {};
   alert( user.aaa === undefined ); // true means there is no such attribute.
Copy the code
  1. The in operator
    let user = { name: "John".age: 30 };
    alert( "age" in user ); // true, user.age exists
    alert( "blabla" in user ); // false, user.blabla does not exist.
    
    // Can be a variable judgment
    let user = { age: 30 };
    let key = "age";
    alert( key in user ); // true, the attribute "age" exists
    Copy the code

Note that both undefined and in return true if the property is undefined

For in iterates over all the keys

let user = {
  name: "John".age: 30.isAdmin: true
};
for (let key in user) {
  // keys
  alert( key );  // name, age, isAdmin
  // Attribute key value
  alert( user[key] ); // John, 30, true
}
Copy the code

Property traversal sort

  • Integer attributes are sorted
  • Other properties are displayed in the order they were created

Sort by integer type

let codes = {
  "49": "Germany"."41": "Switzerland"."44": "Great Britain"./ /.. .
  "1": "USA"
};
for(let code in codes) {
  alert(code); // 1, 41, 44, 49
}
Copy the code

In order of creation

let user = {
  name: "John".surname: "Smith"
};
user.age = 25; // Add one
// Non-integer attributes are sorted in the order they were created
for (let prop in user) {
  alert( prop ); // name, surname, age
}
Copy the code

conclusion

Objects are associative arrays with some special properties. They store attributes (key-value pairs), where:

  • The key of the property must be a string or symbol (usually a string).
  • Values can be of any type.

We can access attributes as follows:

  • Dot notation:obj.property.
  • The square bracketsobj["property"]Square brackets allow you to retrieve keys from variables, for exampleobj[varWithKey].

Other operations:

  • Delete attributes:delete obj.prop.
  • Check for the presence of a given key attribute:"key" in obj.
  • Traversal object:for(let key in obj)Cycle.

Object reference and copy

Objects are stored and copied by referencing addresses, whereas primitive types are stored directly as actual strings, numbers, or true false.

Object replication

It’s just a simple reference copy, and everything is still the same object

let user = { name: "John" }; 
let admin = user; // Copy the reference
// The user and admin operations are equivalent
Copy the code

Reference to compare

let a = {};
let b = a; // Copy the reference
alert( a == b ); // true, both reference the same object
alert( a === b ); // true
// Objects defined by literals are two independent reference addresses
let a = {}; 
let b = {}; // Two independent objects
alert( a == b ); // false
Copy the code

Object copy/merge

Loop assignment by iterating through key values

let user = {
  name: "John".age: 30
};
let clone = {}; // New empty object
// Copy all attributes from user to it
for (let key in user) {
  clone[key] = user[key];
}
// Clone is now a completely separate object with the same content
clone.name = "Pete"; // Change the data in it
alert( user.name ); // The name attribute in the original object is still John
Copy the code

The use of the Object. Assgin

Object.assign(dest, [src1, src2, src3…] )

Merging multiple attributes

let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// Copy all the attributes in permissions1 and permissions2 to user
Object.assign(user, permissions1, permissions2);
// Now user = {name: "John", canView: true, canEdit: true}
Copy the code

Object.assign Clone an Object

let user = {
  name: "John",
  age: 30
};
let clone = Object.assign({}, user); 
Copy the code

Note that objects that are likely to be copied are nested objects, which is where deep copying is required.

The garbage collection

accessibility

“Reachable” values are those that are accessible or available in some way. They must be stored in memory.

  1. Here is a basic set of inherently reachable values that obviously cannot be released.
  • Global variables.
  • Local variables and arguments to the current function.
  • When a nested call is made, the variables and arguments of all functions on the current call chain are called.
  • These values are calledThe rootroots
  1. A value is considered reachable if any other value can be accessed from the root through a reference or chain of references.

In the JavaScript engine there is something called the garbage collector that executes in the background. It monitors the status of all objects and removes those that are no longer reachable.

Scenario 1

// User is the object referenced below the root
let user = {
  name: "John"
};

user = null;// When null is set, the original {name: "John"} object is no longer referred to, and will be recycled
Copy the code

Scenario 2 is correlated

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  }
}

let family = marry({
  name: "John"
}, {
  name: "Ann"
});
Copy the code

// When executing the following code

delete family.father;
delete family.mother.husband;
Copy the code

The following results

Since John is no longer referenced, although he points to Ann, the garbage collection principle is reachable. So John will be recycled.

  • Family = null;
  • All objects will be reclaimed.

Recovery algorithm

The Mark-and-sweep garbage collector is optimized by periodically marking and cleaning:

  • Generational collection
  • Incremental collection
  • Spare time to collect

conclusion

Main contents to master:

  • Garbage collection is automatic and cannot be enforced or prevented.
  • When an object is reachable, it must exist in memory.
  • Being referenced is not the same as being accessible (from a root) : a set of interconnected objects may not be reachable as a whole.

Object methods

Functions that assign values to object properties through function expressions are called methods.

let user = {
  name: "John".age: 30
};
1 / / way
user.sayHi = function() {
  alert("Hello!");
};
user.sayHi(); // Hello!
// Mode 2 can also be declared first and then assigned
function sayHi() {
  alert("Hello!");
};
user.sayHi = sayHi;
Copy the code

Methods shorthand

1 / / way
user = {
  sayHi: function() {
    alert("Hello"); }};2 / / way
let user = {
  sayHi() { 
    alert("Hello"); }};Copy the code

Methods in the “this”

This is the object on which the method is called. What is the object “before the dot sign”

let user = {
  name: "John".age: 30.sayHi() { 
    alert(this.name);// The current object
     / / equivalent to thealert(user.name); }};Copy the code

This can be used for any function, even if it is not a method of an object.

function sayHi() {  alert( this); }// No error here, output window
Copy the code
  • The value of this in strict mode is undefined
  • The value of this in non-strict mode is window

This determines the content of the value through the code context. It’s calculated at runtime,

let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
  alert( this.name );
} 
user.f = sayHi;
admin.f = sayHi; 
user.f(); // John (this == user)
admin.f(); // Admin (this == Admin)
Copy the code

Arrow functions don’t have this

let user = {
  a: "a".sayHi() {
    let fn = () = > alert(this.a); fn(); }}; user.sayHi();// a
Copy the code
  • thisThe value of is obtained while the program is running.
  • A function may be used when it is declaredthisBut thisthisIt has a value only when the function is called.
  • You can copy functions between objects.

The constructor

Create an object through a constructor, equivalent to a literal {… }

  1. Suggested name: Start with a capital letter.
  2. They can only be made"new"Operator to execute.

Create a process

  1. A new empty object is created and assigned tothis.
  2. The function body executes. Usually it will modifythisAdd a new attribute to it.
  3. returnthisThe value of the.
function User(name) {
  // this = {}; (Implicitly created)
  // Add attributes to this
  this.name = name;
  this.isAdmin = false;
  // return this; (Implicit return)
}
let user = new User("Jack")
// equivalent to a literal
let user = {
  name: "Jack".isAdmin: false
};
Copy the code

Any function (except the arrow function) can be used as a constructor. That is, you can run the constructor through new. The main implementation: reusable object creation code

The new function () {… }

  • Execute the function immediately anonymously
  • Code for creating a single complex object,
let user = new function() {
  this.name = "John";
  this.isAdmin = false;
};
Copy the code

Constructor pattern test: new.target

function User() {
  alert(new.target);
}
// no "new" :
User(); // undefined just calls the method
/ / with "new" :
new User(); // function User { ... } here an object is instantiated
Copy the code

Constructor return

  • ifreturnIf an object is returned, the object is returned instead ofthis.
function BigUser() {
  this.name = "aaa";
  return { name: "bbb" };  // <-- returns this object
}
alert( new BigUser().name );  // aaa gets that object
// Return normal
function SmallUser() {
  this.name = "John";
  return; // <-- returns this
}
alert( new SmallUser().name );  // John
Copy the code

Omit the parentheses

let user = new User; // <-- no arguments
/ / is equivalent to
let user = new User();
Copy the code

Methods in the constructor

function User(name) {
  this.name = name;
  this.sayHi = function() {
    alert( "My name is: " + this.name );
  };
}
let john = new User("John");
john.sayHi(); // My name is: John
Copy the code

Optional chain “? .”

If? . If the left part is not present, the operation will stop immediately (” short-circuit effect “)

let user = {}; // User has no address attributealert( user? .address? .street );// undefined (no error)

let user = null; alert( user? .address );// undefinedalert( user? .address.street );// undefined
Copy the code

? Variables before. Must be declared

// ReferenceError: user is not defineduser? .address;Copy the code

? The.() method call has a judgment

let userAdmin = {
  admin() {
    alert("I am admin"); }};letuserGuest = {}; userAdmin.admin? . ();// I am adminuserGuest.admin? . ();// There is no such method.
Copy the code

? .[] Attribute access exists judgment

let user1 = {
  firstName: "John"
};
let user2 = null; // Suppose we cannot authorize this user
let key = "firstName"; alert( user1? .[key] );// Johnalert( user2? .[key] );// undefinedalert( user1? .[key]? .something? .not? .existing);// undefined
// Optimize the delete attribute
deleteuser? .name;Copy the code

? .Cannot be used for assignment

let user = null; user? .name ="John"; // Error, no effect
// undefined = "John"
Copy the code

conclusion

Optional chain? There are three forms of grammar:

  1. obj? .prop– ifobjIf it exists, returnobj.propOtherwise returnundefined.
  2. obj? .[prop]– ifobjIf it exists, returnobj[prop]Otherwise returnundefined.
  3. obj.method? . ()– ifobj.methodIf exist, callobj.method()Otherwise returnundefined.

Symbol type

  • The property key of an object can only be of type string or Symbol
  • The “Symbol” value represents a unique identifier. Used to implicitly protect variables, much like the Concept of private modifiers in Java.
  • The advantage is that when using a third-party library, you want to define new attributes, if the original third-party library has for.. In, will not be iterated, does not affect the original code.
// id is an instantiated object of symbol
let id = Symbol(a);// id is a Symbol described as "id"
let id = Symbol("id");
Copy the code

Symbol is not automatically converted to a string

let id = Symbol("id");
alert(id); // Type error: unable to convert Symbol value to string.
//.description or.tostring () should be used
let id = Symbol("id");
alert(id.description); // id
Copy the code

You can set attributes dynamically and cannot access variables directly in user.id mode. You can only access variables through user[ID]

let user = { // Belongs to another code
  name: "John"
};
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // We can use Symbol as the key to access data
Copy the code

Symbol in object literals

let id = Symbol("id");
let user = {
  name: "John",
  [id]: 123 // Instead of "id" : 123
};
Copy the code

In the for… In will be skipped

The Symbol attribute does not participate in for.. In circulation. Keys (user) is also not supported

let id = Symbol("id");
let user = {
  name: "John".age: 30,
  [id]: 123
};
for (let key in user) alert(key); // name, age (no symbols)
// Use the Symbol task to access directly
alert( "Direct: " + user[id] );
Copy the code

Object.assign can copy related information

let id = Symbol("id");
let user = {
  [id]: 123
};
let clone = Object.assign({}, user);
alert( clone[id] ); / / 123
Copy the code

A global symbol

Global access, unified storage in the registry. Unified management

// Read from the global registry
let id = Symbol.for("id"); // If the Symbol does not exist, create it
// Read again (possibly in a different location in the code)
let idAgain = Symbol.for("id");
// Same Symbol
alert( id === idAgain ); // true
Copy the code

Symbol.keyFor

As long as the symbol is global, the name can be obtained from the symbol

// Get Symbol by name
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");
// Get the name from Symbol
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id
Copy the code

Non-global symbols can access names using description

let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");
alert( Symbol.keyFor(globalSymbol) ); // name, global Symbol
alert( Symbol.keyFor(localSymbol) ); // undefined, not global
alert( localSymbol.description ); // name
Copy the code

Object-raw value conversion

Automatically called by many built-in functions and operators that expect raw values as values.Copy the code

There are three types of hints:

  • "string"(foralertAnd other operations that require strings.)
  • "number"(For mathematical operations)
  • "default"(A few operators)

Call logic press

  1. objSymbol.toPrimitive
  2. Hint is a string callobj.toString()obj.valueOf()
  3. Hint is the number/default callobj.valueOf()obj.toString()

ToPrimitive

Symbol. ToPrimitive’s built-in Symbol, which is used to name the conversion method

obj[Symbol.toPrimitive] = function(hint) {
  // Return a raw value
  // hint = one of "string", "number", and "default"
} 
/ / case
let user = {
  name: "John".money: 1000[Symbol.toPrimitive](hint) { alert(hint); }};// Convert demo:
alert(user); // string
alert(+user); // number
alert(user + 500); // default
Copy the code

toString/valueOf

If there is no 'symbol.toprimitive', JavaScript will try to find them and do so in the following order:Copy the code
  • For “String” hint,toString -> valueOf.
  • In other cases,valueOf -> toString.
let user = {
  name: "John".money: 1000./ / to hint = "string"
  toString() {
    return "string"
  },
  // For hint="number" or "default"
  valueOf() {
    return "number/default"}}; alert(user);// string
alert(+user); // number/default
alert(user + 500); // number/default
Copy the code

There’s only one way to do this, and that’s toString

let user = {
  name: "John".toString() {
    return this.name; }}; alert(user);// toString -> John
alert(user + 500); // toString -> John500
Copy the code

Note the return value: you must return a raw value, not an object.

Advanced use:

let obj = {
  // toString handles all conversions without other methods
  toString() {
    return "2"; }}; alert(obj *2); // 4, the object is converted to the original value string "2", which is then multiplied to the number 2.
Copy the code