Note: This article is chapter 5 of the relearning JavaScript advanced Programming series. About “relearning JavaScript advanced programming” is a review of the basics of JS learning.

1. What is object orientation

One hallmark of object-oriented languages is that they all have the concept of classes, from which you can create any number of objects with the same properties and methods. But, again, mentioned earlier. ES has no concept of classes, so its objects are different from those in class-based languages.

Definition of an object: ‘An unordered collection of attributes that can contain base values, objects, or functions. ‘Strictly speaking, this is equivalent to saying that an object is a set of values in no particular order. Each property or method of an object has a name, and each name maps to a value. So we can think of an ES object as a hash table: nothing more than a set of name-value pairs, where the values can be data or functions.

Each object is created based on a reference type, which can be either a native type discussed in the previous chapter or a custom type.

2. Create an object

The simplest way is to create an instance of Object and then add properties and methods to it.

let p = new Object() p.name = 'js' p.age = 20 p.job = 'jizhe' p.sayName = function() { alert(this.name) } p.sayName() //  jsCopy the code

3. Factory mode

Factory pattern: Abstracts the process of creating concrete objects. Given that classes cannot be created in ES, a specific function encapsulates the details of creating objects with a specific interface.

function p(name, age, job) { let o = new Object() o.name = name o.age = age o.job = job o.sayName = function() { alert(this.name) } return o } Let p1 = p('tc', 30, 'laosu ') let p2 = p('bd', 22, 'bd') p1.sayname // tc p2.sayname //Copy the code

The function p() builds a Person object with all the necessary information based on the parameters it accepts. This function can be called an infinite number of times, and each time it returns an object containing a method with three properties. The factory pattern solves the problem of creating multiple similar objects, but it does not solve the problem of object recognition (how to find the type of an object)

4. Constructor pattern

As described in the previous chapters, the constructors of ES can be used to create objects of a specific type. Native constructors, such as Object and Array, automatically appear in the execution environment at run time. In addition, you can create custom constructors to define properties and methods of a custom object type. As follows:

function p(name, age, job) { this.name = name this.age = age this.job = job this.sayName = function (){ alert(this.name) } } let p1 = new P(' TC ', 33, 'haha') let p2 = new P('gg', 32, 'haha') p1.sayname () // haha p2.sayname () //Copy the code

In the example above, the p() function replaces the function in the previous section. In addition to the same content code, there are the following differences:

  • There is no explicit creation object
  • Attributes and methods are assigned directly to this object
  • No retrun statements
  • The other function p is capital. Constructors always begin with a capital letter. Non-constructor starts in lower case.

In addition, if you want to create an instance of P, you must use the new operator. Calling the constructor in this way actually goes through the following four steps:

  • Create a new object
  • Assign the constructor’s scope to the new object (so this refers to the new object)
  • Execute the code in the constructor (add attributes to this object)
  • Return a new object

Object’s constructor property, originally used to identify the object type. However, when it comes to detecting object types, the Instanceof operator is more reliable.

Instanceof determines whether an object is an instanceof another objectCopy the code

Advantages: Compared to the factory pattern, the constructor pattern can identify its instance as a specific type.

Note: If constructors defined in this way are defined in a Global object, the instaceof operator and construcotr properties will always assume that constructors are queried in Global scope unless otherwise noted.

4.1 Treat constructors as functions

The only difference between constructors and other functions is the way they are called. However, constructors are also functions, and there is no special syntax for defining constructors. Any function called with the new operator can be used as a constructor; Any function that is not called by the new operator is just as good as a normal function.

// let p = new Person('tc', 22, 'ha ha ha ') p.sayname 'oo') // add to window windwo.sayname // gc // call let o = new Object() p.call (o, 'new', 33, 'suzhou') o.sayName // newCopy the code

4.2 Constructor problems

Constructors, while useful, have their drawbacks. The main problem with using constructors is that each method has to be recreated on each instance.

5. Prototyping

Each time we create a function we have a Prototype property, which is a pointer to an object. The purpose of this object is to contain properties and methods that can be shared by all instances of a particular type. If taken literally, prototype is the prototype object of the instance of the object created by calling the constructor. The advantage of using a prototype object is that all object instances can share the properties and methods it contains. In other words, instead of defining the object instance information in the constructor, you can add that information directly to the prototype object.

5.1 Understanding prototype objects

Whenever a new hansook is created, a Prototype property is created for the function according to a specific set of rules, which points to the function’s prototype object. By default, all prototype objects automatically get a constructor property that contains a pointer to the function where the Prototype property resides. With this constructor, we can continue to add other properties and methods to the prototype object.

After a custom constructor is created, its prototype object acquires only the constructor attribute by default; As for the other methods, they are inherited from Object. When a constructor is called to create a new instance, the inside of the instance contains a pointer (inner property) to the constructor’s prototype object. In many implementations, the name of this internal property is proto, and it is accessible through scripts; In other implementations, this property is completely invisible to the script. The really important point to make clear, however, is that the connection exists between the prototype objects instantiated in the constructor, not between the constructor instances

In addition, every time the code reads an attribute of an object, a search is performed for the attribute with the given name. The search starts with the object instance itself. If an attribute with the given name is found in the instance, the value of that attribute is returned; If not, search continues for the prototype object to which the pointer points, looking for the property with the given name in the prototype formation. If the property is found in the stereotype object, the value of the property is returned. That is, when we call p.sayname (), we perform two searches. First, the parser asks: does instance P have the sayName attribute, if not, does p’s prototype have the sayName attribute, and if so, reads the function stored in the prototype object.

Although you can access values stored in the stereotype through the object instance, you cannot override values in the stereotype through the object instance. If we add a property in the instance that has the same name as a property in the instance stereotype, we create that property in the instance, and that property masks that property in the stereotype.

5.2 Stereotypes and the IN operator

There are two ways to use the IN operator: alone and in for-in loops. When used alone, the IN operator returns true if a given property is accessible through an object, whether it exists in an instance or stereotype. And since the in operator returns true whenever the property is accessible through the object, hasOwnProperty() returns true only if the property exists in the instance, so hasOwnProperty() returns false whenever the in operator returns true, You can determine the attributes in the stereotype.

** Note: ** When a for-in loop is used, it returns enumerable properties accessible through an object, both in the instance and in the stereotype. Instance attributes that mask non-enumerable attributes in stereotypes are also returned in for-in loops.

5.3 Simpler prototype syntax

To reduce unnecessary input and visually encapsulate the functionality of the prototype, it is common to rewrite the entire prototype object with an object literal that contains properties and methods.

function P(){
    
}

P.prototype = {
    name: 'tc',
    age: 22,
    job: 'web',
    sayName: function(){
        console.log(this.name)
    }
}
Copy the code

5.4 Prototype dynamics

Because finding the value in the prototype is a search, any changes we make to the prototype object are immediately reflected in the instance. While attributes and methods can be added to a stereotype at any time, and the changes are immediately reflected in all object instances, rewriting the entire stereotype object is a different story. In addition, when the constructor is called, an __proto__ pointer to the original prototype is added to the instance, and changing the prototype to another object severs the link between the constructor and the original prototype. Pointers in instances point only to prototypes, not to constructors.

5.5 Prototypes for native objects

The stereotype pattern is important not only for creating custom types, but also for all native reference types. All native reference types (Object, Array, String) define methods on their constructors.

typeof Array.prototype.sort     // function
typeof String.prototype.substring   // function
Copy the code

With a prototype of a native object, you can not only get references to all default methods, but also define new methods. You can modify the prototype of a native object just as you modify the prototype of a custom object, so you can add methods at any time.

Important: Although this can be done, it is not recommended to modify the prototype of a native object in a productized program. Adding a method to a prototype of a native object because it is missing from one implementation can cause naming conflicts when running code in another implementation that supports the method, and doing so can accidentally override the native method

5.6 Problems with prototype objects

The prototype pattern also has disadvantages. First, it omits passing initialization parameters to the constructor, resulting in all instances taking the same property values by default. While this is inconvenient to some extent, its biggest problem is its shared nature.

In the prototype, all attributes are shared by many instances, which is ideal for functions. This is fine for properties that contain base values, but is problematic for properties that reference type values.

6. Use a combination of constructor and stereotype patterns

The most common way to create custom types is to use a combination of the constructor pattern and the stereotype pattern. The constructor pattern is used to define instance properties, while the stereotype pattern is used to define method and shared properties. As a result, each instance has its own copy of instance attributes, but also shares references to methods, maximizing memory savings.

7. Dynamic prototyping

All the information is encapsulated in the constructor, and the beauty of using both the constructor and the stereotype is preserved by initializing the stereotype in the constructor. That is, you can decide whether to initialize a prototype by checking whether a method that should exist is valid.

function P(name, age, job) { this.name = name this.age = age this.job = job if(typeof this.sayName ! = 'function') { P.prototype.sayName = fucntion() { console.log(this.name) } } } let p = new P('tc', 23, 'web') p.sayName() // tcCopy the code

The code above adds the sayName() method to the prototype only if it does not exist. This code is executed only when the function is first called. After that, the prototype is initialized and does not need to be modified. Such changes to the prototype are immediately reflected in all instances. Alternatively, the if statement can check for any properties or methods that should exist after initialization.

** Note: ** When using the dynamic prototype pattern, you cannot rewrite a prototype using object literals. Rewriting a prototype when an instance has already been created severs the link between the existing instance and the new prototype.

8. Parasitic constructor pattern

Create a function that simply wraps the code that created the object and then returns the newly created object.

Note: There is no relationship between the object returned by the parasitic constructor pattern and the constructor or its stereotype properties, that is, the object returned by the constructor is no different from the object created outside the constructor. For this reason, you cannot rely on the Instanceof operator to determine the object type.

9. Secure constructor patterns

Like the parasitic constructor pattern, objects created using the secure constructor pattern have no relationship to the constructor, so the instanceof operator has no meaning for such objects.

Welcome to pay attention to the public account [Xiaoyao students]

Re-learn js series

Relearn JS JavaScript introduction

Relearn JS to use JavaScript in HTML

Data types => Data types

Relearn the basic JavaScript concepts of JS (middle) => operator

Relearn the basic JavaScript concepts of JS (part 2) => operator

Relearn JavaScript variables, scope, and memory issues in JS

Relearn Javascript reference types

ES6 Introduction series

ES6 Introduction to let and cont

ES6 introduction to variable deconstruction assignment

ES6 starter string extension

ES6 – An extension to get started with re

ES6 introduction to numerical extension

Extension of ES6 introductory functions

ES6 introduction to the array extension

Extensions to ES6 starter objects

ES6 Symbol for beginners

Git tutorial

Front-end Git basics tutorial