Before the order

About objects, THE Java I have learned before is a pure object-oriented language. JavaScript can only be said to be based on objects before, but with the emergence of ES6, the idea of Object-Oriented JavaScript has become more clear

Here’s a quick summary of the chapter on object-oriented programming in JavaScript Advanced Programming!

Understanding object

ES6 defines an object as an unordered collection of attributes with no particular order. Each attribute and method is a set of key/value pairs

There are two ways to create objects

1. Create an Object instance

let person = new Object()
person.name = 'lwj'
Copy the code

2. Literal way

let person = {
    name:'lwj'
    ...
}
Copy the code
The internal characteristics of an attribute

ES6 provisions of each attribute are internal characteristics We can use the Object. GetOwnPropertyDescriptor () to view the properties of the internal characteristics

/ / parameters list 1 2 attribute names the console Object name parameters. The log (Object. GetOwnPropertyDescriptor (book, "year"))Copy the code
Data attributes

The four properties of the property

[[64x]] Specifies whether the property of [[64X] can be deleted by delet. The default is true

2, [[Enumerable]] sets an attribute that can be used for… In loop traversal defaults to true

3, [[Writable]] sets whether properties can be modified (recopied) default true

4, [[value]] Storage attribute value default undefined

You can use Object.defineProperty() to change the internal attributes of an Object

Parameter list of object.defineProperty () : Parameter 1: Object parameter 2: Object attribute parameter 3: Enumerable, Writable, and value let person = {name:' LWJ ', a different descriptor object {} sets the property of different, enumerable, writable, and different property. Age = '18'} // Set the name property to unchangeable object.defineProperty (person,'name',{writable:'false'})......Copy the code

If the property is set to false, the property is missing. In non-strict mode, operations on the property are ignored and in strict mode, an error is reported

The default Property of Enumerable and writable is false when you add a different Property with Object.property (), and runs without any additional information

Student Object.Property(person,'job', {vaule: 'student'}) Object. GetOwnPropertyDescriptor (person, 'job') / / the return value {value: 'student', writable: false, enumerable: false, configurable: false }Copy the code
Accessor properties

Understanding: Provides features for get and SET methods to simulate private properties in object-oriented programming

Accessor properties do not contain the value property and therefore do not have the corresponding writable property

[[64x]] Specifies whether the property of [[64X] can be deleted by delet. The default is true

2, [[Enumerable]] sets an attribute that can be used for… In loop traversal defaults to true

3, [[Get]] Get function read attribute is called by default undefined

4, [[Set]] Set function write attribute read default undefined

Accessor properties must be defined using Object.defineProperty()

Let book = {year_:2017, edition:1} Defines year_'s private accessor property object.defineProperty (book,'year',{get(){return this.year_}, set(newValue){ if(newValue > 2017){ this.year_ = newValue this.edition += newValue-2017 } } }) Object. GetOwnPropertyDescriptor (book, 'year') / / the return value {get: [Function: get], set: [Function: set], enumerable: false, configurable: false }Copy the code
Defining multiple properties

Define multiple attributes at once and the descriptor Object.defineProperties()

Object.defineProperities( book , { year_:{ value:'2018' }, edition:{ value:1 }, year:{ get(){ return this.year_ } set(){ ... }}})Copy the code

ES2017 through the characteristics of each attribute in the Object name display function Object. The getOwnPropertyDescriptors (obj) : the incoming Object name

Merge/blend objects

Object. The assign () method

Parameter list: Parameter 1 Target object parameter 2.. N 1-N original target merging rules: Let obj1 = {set a(value){console.log(value)}} let obj2 = {get b(){let obj2 = {get b(){ Console. log('obj2 run') return 'aaa'}} object. assign(obj1,obj2) // The get method of the source Object returns AAA as an argument to set but does not assign parameters to set  console.log(obj1) //{ set a{} }Copy the code

Object.assign() is a shallow copy of each target Object that copies only references to the Object

Object.assign() does not have a rollback mechanism if an error occurs during the copy and only possible parts are copied

let dest,src;

dest = {}
src = {
	a:'foo',
	d:'kkk',
	get b (){
		throw new Error();
	},
	C:'bar'
}

try{
     Object.assign(dest,src)
}catch(err){
	
}
console.log(dest) //{ a: 'foo', d: 'kkk' }


Copy the code
Object enhanced syntax

1. Attribute shorthand

Let name = 'LWJ' let person = {name:name}Copy the code

2. Computable properties

Const nameKey = 'name' const ageKey = 'age' const obj4 = {[namekey]:' LLL ', [agekey]:18 } console.log(obj4) {namekey:'name',agekey:'age'}Copy the code

The brackets [] tell the runtime to evaluate the contents as JavaScript expressions

3. Method shorthand & computable properties

const methodkey = 'sayName'
const obj5 = {
	[methodkey](name){
		console.log(`my name is ${name}`)
	}
	
}
console.log(obj5)
obj5.sayName('lisa') 
Copy the code

4. Object deconstruction

Const obj6 = {cname:' LWJ ', cage:'18'} const {cname:reName,cage:reAge} = obj6 cage ,cjob = 'student'} = obj6 console.log(`name:${reName},age:${reAge}`) //name:lwj,age:18 console.log(cname) //lwj console.log(cage) //18 console.log(cjob) //undefinedCopy the code

ToObject() cannot convert null and undefinedNull and undefined cannot be deconstructed

Deconstructing an object into a pre-declared property requires wrapping the structure expression in a ()

let rekname,rekage let obj7 = { kname:'lwj', Kage: 55} / / use a timer to avoid error setTimeout (() = > {({kname: rekname, kage: rekage} = obj7) / / in the node environment runtime () before the code will be ahead of the let's statement execution At this moment, an console.log(rekname,rekage)// },0)Copy the code

Nested structure Deconstructing an object when it has nested objects directly assigns references to the object in the source object

Let person = {name:' LWJ ', job:{title:' ABC '}} // Declare the title variable to assign person.job.title to let {job:{title}} = personCopy the code

Partial deconstruction If an error is reported during the deconstruction process, only the property before the error is deconstructed is called partial deconstruction

Argument deconstruction Does not affect the arguments object’s ability to take the structured object as one of its items

Method to create an object

You can create constructs using Object constructors and literals, but it cannot reuse code

The factory way
let personFac = function(name,age,job){ let o = ne Object() o.name = name o.age = age o.obj = job o.sayName = Per1 = personFac(' LWJ ',18,'teacher') personFac(' LWJ ',18,'teacher') personFac(' LWJ ',18,'teacher') per1.sayName() //lwj per2 = personFac('lmm',18,'teacher') per2.sayName() //lmmCopy the code
Is structured
Function Person(name,age,job){this.name = name; this.age = age; this.job = job; SayName = function(){console.log(this.name)}} let per1 = new Person(' LWJ ',30,'teacher') let per2  = new Person('lmm',15,'stuedent')Copy the code

New operator

(1) Create a new object in memory

(2) Set the prototype pointer to the number constructor’s prototype property per1.proto == Person.prototype

(3) Point the constructor’s this to the new instance object

(4) Execute the code in the construct

(5) If the value is null, the newly created object is returned

Constructors are functions: any function called with the new operator is a constructor and is a normal function

A normal function call will add all the attributes inside the function to the object that this points to and when we use a function and we don’t do any call, apply, bind on the object that this points to, by default it points to the global object

So calling a normal function adds all the properties of the normal function to the global object by default (call/apply changes this to point to and all properties are added to the new object bound to this).

Constructor problem The definition of a function when using constructors for object creation

function Person(){ this.name = 'lwj' this.sayName = function(){ console.log(this.name) } } //this.sayName = new Function("console.log(this.name)") // Each new object creates a new Function with the same logic, resulting in a waste of resourcesCopy the code

You can extract the definition of an object function outside the construct

 function Person(){
         this.name = 'lwj'
         this.sayName = sayName
     }
let sayName = function(){
            console.log(this.name)
         } 
Copy the code

Doing so solves the problem of repeating definitions of the same logical code but creates a more serious problem of global scope confusion

The prototype pattern

Each function creates a Prototype property on which all properties and methods can be shared by the object instance

We use the properties of stereotypes to define objects

function Person1(){} Person1.prototype.name = 'yuanxingmode' Person1.prototype.age = 18 Person1.prototype.job = 'teacher' Person1.prototype.sayName = function(){ console.log(this.name) } let p1 = new Person1() let p2 = new Person1()  p1.sayName() //yuanxingmode p2.sayName() //yuanxingmodeCopy the code

I won’t go into detail about the prototype here, but I’ll write a separate summary of the prototype later

Attached is some code for the learning prototype

//function Stu(){} Stu(){} Stu. Prototype. name = 'LWJ' stu. prototype.job = 'cooke' let stu1 = new Stu () / / instance has nothing to do with the constructor has something to do with the prototype of the constructor. The console log (Stu. Prototype) console. The log (Stu) prototype) constructor) Console. log(stu1.__proto__) console.log(stu1.__proto__.constructor) // Prototype API //isPrototypeOf() determines whether the passed argument uses its prototype object The console. The log (Stu. Prototype. IsPrototypeOf (stu1)) / / Object. GetPrototypeOf () convenient to obtain an instance Object prototype console.log(Object.getPrototypeOf(stu1) == stu1.__proto__) console.log(Object.getPrototypeOf(stu1) == Stu.prototype) Console. log(object.getProtoTypeof (stu1)) // object.setProtoTypeof () writes a new value to the prototypeof the instance (overriding the inheritance relation of the instance Object) let cat = {name:'kk', age:1 } Object.setPrototypeOf(stu1 , cat) console.log(stu1.name) console.log(stu1.age) console.log(stu1.__proto__) console.log(Object.getPrototypeOf(stu1)) Console. log(stu1.__proto__ === cat) // However, using object.setPrototypeof () to override the prototype pointing of the instance seriously affects the code performance // We can also use object.create () To create and specify a new prototype object let dog = {name:'dd', Age :4} stu1 = object.create (dog) console.log(stu1) console.log(stu1.__proto__) //in operator // 2, for... In the console. The log (' -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the in operator -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ') let Stu1 = function () {} Stu1. Prototype. Name = 'LWJ' Stu1.prototype.age = 18 let stu2 = new Stu1() console.log('name' in stu2) stu2.job = 'student' console.log('job' in stu2) console.log(stu2.hasOwnProperty('name')) console.log(stu2.hasOwnProperty('job')) console.log(stu2) Console. log(stu2.__proto__) function hasOwnPrototype(obj,property){//! // Property in obj and the property exists on the object instance or prototype object if(! Obj. HasOwnProperty (Property) && Property in obj){return true} else{return false}} //for in loops over all iterable properties in the instance object and prototype object For (a in stu2){console.log(a)} console.log('-- ') In enumerable:false Object.defineProperty(Stu1. Prototype,'name',{enumerable:false}) console.log(Stu1 For (a in stu2){console.log(a)} console.log('-- ')} stu2.name =' CCC ' For (a in stu2){console.log(a)} object.defineProperty (stu2,'job',{enumerable:true, value:'teacher' }) console.log(stu2.job) console.log(stu2) console.log(Object.keys(stu2)) Console. The log (Object. GetOwnPropertyNames (stu2)) / / get the value of the Object array Object. The values the console. The log (Object) values (stu2)) The console. The log (Object. Entries (stu2)) / / using the Object directly to prototype assignment console. The log (Stu1. Prototype) console. The log (Stu1. Prototype. Constructor) //Stu1.prototype = { // name:'aaa', / / job: 'docotor' / /} / / console log (Stu1. Prototype). / / the console log (Stu1. Prototype. Constructor) / / faults lead to the constructor is no longer points to the structure of the original Constructor: Stu1 name:'aaa', job:'docotor'} //constructor default is not for.. Enumerable: // You can modify enumerable directly with Object.defineProperty() Object.defineProperty(Stu1.prototype,'constructor',{ enumerable:false, value:Stu1 }) console.log(Stu1.prototype) console.log(Stu1.prototype.constructor) delete stu2.name console.log(stu2.name)Copy the code

It is important to note that instances have nothing to do with constructors and everything to do with constructors prototypes

inheritance

Prototype chain inheritance, embeded construction inheritance, combination inheritance, original type inheritance, parasitic inheritance, parasitic combination inheritance

Prototype chain inheritance
let FatherPro = function(){ this.fname = 'father' } FatherPro.prototype.sayfName = function(){ return this.fname } let SonPro = function(){this.sname = 'son'} sonpro.prototype = new FatherPro( / / FatherPro will be added to the constructor of the attributes on the prototype of SonPro SonPro. Prototype. SaysName = function () {return enclosing sname} let p1 = new SonPro () / / as a result of SonPro prototype assignment to FatherPro instance objects / / so call SonPro constructor attribute is actually pointing FatherPro console. The log (SonPro. Prototype. Constructor) //FatherPro(){} // constructor for SonPro's instance object likewise console.log(p1.__proto__. Constructor) //FatherPro(){}Copy the code

Disadvantages of prototype chain inheritance: ① Strong sharing for reference object types all instances will share the same reference space

(2) When a subclass is instantiated, it cannot pass in arguments to its parent class

Embezzled construction inheritance
let Father = function(name = 'lwj'){ this.name = name this.hobbies = ['game','ball'] this.sayName = function(){ Console.log (this.name)}} let Son = function(){// Call the call method of the parent class in the subclass constructor to point to the subclass // Put the referenced properties in the parent class into the constructor to copy the referenced properties through construction inheritance Father. Call (this,' HMM ') this.age = 19}Copy the code

Advantages: The subclass constructor can pass arguments when calling the parent constructor

Disadvantages: attributes can only be passed through constructors and method subclasses cannot access methods on the parent class’s constructor prototype

Combination of inheritance

Inheriting properties and methods on stereotypes using stereotype chains inheriting instance properties using stolen constructors

let Father1 = function(name = 'lwj'){ this.name = name this.age = 15 this.hobbies = ['basketball','pingpang'] } Father1. Prototype. SayName = function () {the console. The log (enclosing name)} let Son1 = function () {/ / father structure all the instance attributes and methods Father1.call(this)} // son1.prototype = new Father1()Copy the code

Disadvantages: Calling the parent constructor twice causes a certain loss in efficiency

Primary inheritance

You can use stereotypes to transfer information between objects without defining a type

Function object(o){function F(){} function object(o){F(){} Let Father3 = function(){this.name = 'LWJ'}Copy the code

The above custom inheritance function ES6 provides us with a normalized method object.create ()

Object.create() can take two arguments. The first argument is the instance Object and the second argument is some additional properties. The second argument is passed in the same way as Object.getProperties() Object.create(per,{ name:{ writable:false, value:'ccc' }, age:{ writable:'aaa', value:18 } })Copy the code

Suitable for sharing information between objects without the need to create separate constructors

Parasitic inheritance

You can add additional attributes or methods to an object in a defined factory and then return the object

    function newObj(obj){
            let clone = Object.create(obj)
            clone.sayName = function(){
                    console.log(this.name)
            }
            return clone
    }
Copy the code

Disadvantages This style of inheritance can make inheritance difficult to reuse similar to construction inheritance

Parasitic combinatorial inheritance

The hybrid prototype chain inheritance method of embeded structure inheritance attribute is adopted

Function inherit(per,stu){let proType = object(per. Prototype) constructor = per Prototype = proType // assignment object}Copy the code

class

The concepts of stereotypes and constructors are still used behind classes

Define the class

Class declarations and class expressions

Class person {}

Let person = class {}

The difference between a class and a function is that a function declaration elevates the class declaration but not the class definition block-level scope

By default, the code in the class is executed in strict mode

Class names can be changed at will

Let Person = class PersonName {} person.name //PersonName PersonName //ReferenceError // can be accessed via the person.name attribute But PersonName cannot be accessed directlyCopy the code
Class constructor

Not defining a construct creates an empty construct by default

Class Person {constructor(){}} new Person() // Creating an instance using new tells the class to call the constructor constructor methodCopy the code

New a class performs the same steps as new a function

The class constructor returns a this object after execution as the this of the instantiated object and the object is destroyed if nothing references the instance object


Unfinished…