JavaScript Advanced Programming Reading Sharing Chapter 8 - 8.1 Understanding Objects

JavaScript Advanced Programming (4th Edition) Reading Sharing Note Recording

Applicable to comrades who are just getting started

  •  The usual way to create custom objects is to create a new instance of Object and then add properties and methods to it.
let person = new Object()
person.name = 'Tom'
person.age = 18
person.sayName = function(){
    //示 this.name 的值,这个属性会解析为 person.name。
    console.log(this.name) // Tom  
}

The above code creates an object named person with two properties (name, age) and one method (sayName).

  • Create objects using object literals
let person = {
    name:'Tom',
    age:18,
    sayName(){
        console.log(this.name) //Tom
    }
}

attribute type

There are two types of properties: data properties and accessor properties .

data attribute

Data attributes have 4 properties that describe their behavior:
  •  [[Configurable]] : Indicates whether the property can be deleted and redefined by delete , whether its characteristics , and whether it can be changed to an accessor property. By default, this feature is true
  •  [[Enumerable]] : Indicates whether the attribute can be returned by a for-in loop. By default, this feature is true.
  •  [[Writable]] : Indicates whether the value of the attribute can be modified. By default, this feature is true.
  • [[Value]] : Contains the actual value of the property. This is where the aforementioned property values ​​are read and written. The default value of this feature is undefined .
To modify the default properties of a property, you must use the Object.defineProperty() method.
This method receives 3 parameters : 1. The object to add the attribute to, 2. The name of the attribute and a descriptor object. The last parameter, that is, the attributes on the descriptor object can include: configurable , enumerable , writable and value , corresponding to the names of related features one by one.
For example:
let person = {}
Object.defineProperty(person,'name',{
    writable:false,
    configurable:false,
    value:'Tom'
})

console.log(person.name) // Tom

//这里修改person对象的name值,是无效的,因为上面writable:false,就说明属性的值不可被修改
person.name = 'Jerry'
console.log(person.name) // Tom

//这里删除person对象的name属性,是删除不了的因为上面configurable:false,就说明该属性不能被delete
delete person.name
console.log(person.name) // Tom

Note :

  • When calling Object.defineProperty() , if the value of configurable , enumerable and writable is not specified, it will default to false .
  • Additionally, once a property is defined as non-configurable (false), it cannot be changed back to configurable. Calling Object.defineProperty() again and modifying any non-writable properties will result in an error
  • There is no way to modify [[Configurable]] or [[Enumerable]] in browsers that don't support Object.defineProperty()

example:

const person = {name:"yd"}
Object.defineProperty(person,"age",{value:21})
person.age = 18
console.log(person) //{name: "jd",age:21}
console.log(Object.keys(person)) // ["name"]

Parse:

​​​​​​​​When Object.defineProperty() is         called , if the values ​​of configurable , enumerable and writable are not specified, they all default to false. ​​​​​​​​

        ​​​​​​​​The properties added using the Object.defineProperty method are not enumerable by default , so Object.keys(person)//["name"].

accessor property

Accessor properties have 4 attributes that describe their behavior
  • [[Configurable]] : Indicates whether the attribute can be deleted and redefined through delete , whether its characteristics can be modified, and whether it can be changed to a data attribute. By default, this property is true for all properties defined directly on the object .
  •  [[Enumerable]] : Indicates whether the attribute can be returned by a for-in loop. By default, this property is true for all properties defined directly on the object .
  • [[Get]] : Get function, called when the property is read. The default value is undefined .
  • [[Set]] : Set function, called when the property is written. The default value is undefined .

Accessor properties cannot be defined directly, Object.defineProperty() must be used .

example:

// 定义一个对象,包含伪私有成员 year_和公共成员 edition 
let book = { 
 year_: 2017, 
 edition: 1
}

Object.defineProperty(book ,"year",{
    get(){
        return this.year_
    },
    set(newVal){
          if(newVal > 2017){
                this.year_ = newVal
                this.edition += newVal - 2017
            }
    }
})

console.log(book.year) // 2017

book.year = 2018
console.log(book.year) // 2018
console.log(book.edition) // 2

Define multiple properties

ECMAScript provides the Object.defineProperties( ) method. This method can define multiple attributes at once through multiple descriptors.
It receives two parameters: 1. The object to add or modify properties for , 2. Another descriptor object with properties corresponding to the properties to be added or modified

let book = {}; 
Object.defineProperties(book, { 
    year_: { 
        value: 2017 ,
        // writable:true
    }, 
    edition: { 
        value: 1 ,
        // writable:true
    }, 
    year: { 
        get(){ 
            return this.year_; 
        },
        set(newValue){
            console.log("1112222222222",newValue)
            if (newValue > 2017) { 
                this.year_ = newValue; 
                console.log("1112222222222" ,this.year_)
                this.edition += newValue - 2017; 
            }
        }
    }
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1


//此时这里修改了year 的值 但是打印没变
book.year = 2018

console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1

Notice:

The only difference is that all attributes are defined at the same time, and the configurable, enumerable , and writable attribute values ​​of the data attributes are all false . ! ! !
So the above modified year still hasn't changed, it is necessary to change writable to true

let book = {}; 
Object.defineProperties(book, { 
    year_: { 
        value: 2017 ,
        writable:true
    }, 
    edition: { 
        value: 1 ,
        writable:true
    }, 
    year: { 
        get(){ 
            return this.year_; 
        },
        set(newValue){
            console.log("1112222222222",newValue)
            if (newValue > 2017) { 
                this.year_ = newValue; 
                console.log("1112222222222" ,this.year_)
                this.edition += newValue - 2017; 
            }
        }
    }
})
console.log(book.year_) // 2017
console.log(book.year) // 2017
console.log(book.edition) // 1

book.year = 2018

console.log(book.year_) // 2018
console.log(book.year) // 2018
console.log(book.edition) // 1

Read property attributes

Use the Object.getOwnPropertyDescriptor() method to get the property descriptor of the specified property. This method takes two parameters: the object where the attribute resides and the name of the attribute whose descriptor is to be retrieved. The return value is an object

Following the book example above:

let descriptor = Object.getOwnPropertyDescriptor(book, "year_"); 
console.log(descriptor.value); // 2017 
console.log(descriptor.configurable); // false 
console.log(typeof descriptor.get); // "undefined" 

let descriptor = Object.getOwnPropertyDescriptor(book, "year"); 
console.log(descriptor.value); // undefined 
console.log(descriptor.enumerable); // false 
console.log(typeof descriptor.get); // "function"

ECMAScript 2017 added the Object.getOwnPropertyDescriptors() static method, the return value is an object

Following the book example above:

let descript =  Object.getOwnPropertyDescriptors(book)
console.log(descript )

print value:

merge object

ECMAScript 6 provides the Object.assign( ) method specifically for merging objects
  • This method receives a target object and one or more source objects as parameters.
  • Note: The property copy of Object.assign( ) is a shallow copy
  • Same-name attribute replacement, if multiple source objects have the same attribute, the last copied value is used.
Example:
let dest ,src, result;

//一个源对象
dest = {}
src = {id:'src'}

result = Object.assign(dest,src)
console.log(result ) // {id:'src'}

//多个源对象
dest = {}
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' }); 
console.log(result); // { a: foo, b: bar }


// 浅复制体现
dest = {} 
src = { a:{b:1}}

result  = Object.assign(dest ,src)
console.log(result) // { a:{b:2}} 因为是浅复制,值指向同一位置
console.log(result.a.b) // 1 
src.a.b = 2
console.log(result.a.b) // 2


//覆盖属性
dest = {id:'dest'}
result  = Object.assign(dest ,{id:'src',a:1},{id:'test',b:2})
console.log(result  ) // {id:'test',a:1,b:2}



Object identification and equality determination

The ECMAScript 6 specification adds Object.is()
  • This method is very similar to ===, which is used to compare whether two values ​​are strictly equal.
  • This method must receive two parameters
Object.is("q","q");      // true
Object.is(1,1);          // true
Object.is([1],[1]);      // false
Object.is({q:1},{q:1});  // false

Difference from ===

//一是+0不等于-0
console.log( Object.is(+0,-0) );  //false
console.log( +0 === -0 )   //true
//二是NaN等于本身
console.log ( Object.is(NaN,NaN) ); //true
console.log (NaN === NaN)  //false

Enhanced Object Syntax

ECMAScript 6 adds many extremely useful syntactic sugar features for defining and manipulating objects

attribute shorthand

ES6 allows the properties of objects to be directly written to variables. At this time, the property name is the variable name, and the property value is the variable value.

const age = 12;
const name = "Amy";
const person = {age, name};
console.log(person) //{age: 12, name: "Amy"}
//等同于
const person = {age: age, name: name}

Computable properties

With computable properties, dynamic property assignment can be done in object literals
const nameKey = 'name'; 
const ageKey = 'age'; 
const jobKey = 'job'; 
let person = { 
 [nameKey]: 'Matt', 
 [ageKey]: 27, 
 [jobKey]: 'Software engineer' 
}; 
console.log(person); // { name: 'Matt', age: 27, job: 'Software engineer' }

Shorthand method name

const person = {
  sayHi(){
    console.log("Hi");
  }
}
person.sayHi();  //"Hi"


//等同于
const person = {
  sayHi:function(){
    console.log("Hi");
  }
}
person.sayHi();//"Hi"

object deconstruction

ECMAScript 6 has added object destructuring syntax, which can use nested data to implement one or more assignment operations in one statement
// 使用对象解构
let person = { 
 name: 'Matt', 
 age: 27 
}; 
let { name: personName, age: personAge } = person; 
console.log(personName); // Matt 
console.log(personAge); // 27
Let the variable directly use the name of the property, then you can use the shorthand syntax.
let person = { 
 name: 'Matt', 
 age: 27 
}; 
let { name, age } = person; 
console.log(name); // Matt 
console.log(age); // 27
        Destructuring does not require variables to be declared in the destructuring expression. However, if you are assigning a value to a previously declared variable, the assignment expression must be enclosed in a pair of parentheses:
let personName, personAge; 
let person = { 
 name: 'Matt', 
 age: 27 
}; 
({name: personName, age: personAge} = person); 
console.log(personName, personAge); // Matt, 27

Guess you like

Origin blog.csdn.net/weixin_42307283/article/details/129263097