Note source: Hook Education – big front end employment Training camp

Content: Notes, thoughts and experiences in the process of learning

Object-oriented programming

What is an object

JS can be understood as an object is a container that encapsulates properties and methods

  • Property: The state of the object
  • Method: The behavior of an object

In real development, an object is an abstract concept that can be understood simply as a collection of data (attributes) and some functionality (methods)

In ES262, an object is defined as an unordered collection of attributes, which can be base values, objects, functions, and so on

Object-oriented programming

Abstract all kinds of complex relations in the real world into objects, and then complete the simulation of the real world by the division of labor and cooperation between objects

Object oriented and process oriented

  • Facing the process is hands-on, we should consider everything clearly, once a link in the middle did not consider the error may occur, we need to cover every aspect, step by step, orderly
  • Object oriented even find an object, through the object command to get the result
  • Object orientation is turning the actor into the leader
  • Object orientation is not a process – oriented replacement, but a process – oriented encapsulation

features

Encapsulation: Encapsulates all procedural programming into objects

Inheritance:

Polymorphism (abstraction) : Passing in different parameters may produce different results

conclusion

In the idea of object-oriented programming, every object is a function center, with a clear division of labor, can complete the task of receiving information, processing data, sending information and so on

Therefore, object-oriented programming is flexible, reusable, easy to maintain and develop, and is more suitable for large-scale software projects with multiple people than traditional procedural programming consisting of a series of functions or instructions

Object oriented and process oriented

// Process oriented programming
// var std1 = {
// name: 'zhang SAN ',
// chengji: 98
/ /},
// std2 = {
// name: 'I ',
// chengji: 70
/ /};

// function go(student) {
// console.log(' name: '+ student.name +' score: '+ student.chengji);
// }

// go(std1);
// go(std2);


// Object-oriented programming
function Student(name, chengji) {
  this.name = name;
  this.chengji = chengji;
  this.go = function () {
    console.log('Name:' + this.name + 'Result:' + this.chengji); }}var std1 = new Student('Joe'.98),
  std2 = new Student('bill'.70);

std1.go();
std2.go();
Copy the code

Object-oriented programming design ideas

  • Abstract a Class constructor
  • Create an instance from the Class constructor
  • Only instance gets the result

How objects are created

  • The new Object() constructor: it’s complicated, we need to define its various properties and methods separately, and it requires multiple objects to write repetitive code
  • Object literals = {} : also complex, we need to write a lot of repetitive code if we need to create multiple objects
  • Factory functions: Simple, we can easily create objects, but the created objects are not very concrete and can not be effectively classified, because they are created by Obiect, we can not know the generated object is constructed by which constructor, and always need to return
  • Custom constructors: easy to use when an object is generated to know which constructor generated itthis.constructorSee which constructor is generated

Determine if the object’s specific constructor type is still neededinstanceofSince this.constructor can be changed and may change

The relationship between constructors and instances

  • A constructor is an abstract template that is abstracted from something concrete
  • The instance object is a concrete object created from this template (constructor) (it may form a different object depending on the parameters passed in)
  • Every power object can passconstructorProperty points to the constructor that created the object (constructorIs the instance attribute of the statement is not very precise, specific later to say)
  • Can be achieved byconstructorAttribute determines the relationship between an instance and a constructorinstanceofMethods to judge, explained later)

Static and instance members

When you create objects using constructors, you can add properties and methods, called members, to the constructor and to the instance you create

Instance members: Inside the constructor, members created through this. XXX can only be called from the instance after the object is created, not directly from the constructor

Static members: Members added to the function itself, excluding all members created through this, can only be called by the constructor, not the instance object

function Perope(name, age) {
  // Instance members: Only instance objects can be called
  this.name = name;
  this.age = age;
  this.sayName = function () {
    console.log(this.name); }}// static member that can only be called by the constructor itself
Perope.sayHello = function () {
  console.log('hello');
}

// Create an instance
var p1 = new Perope('Joe'.19);

// Try calling the instance member
console.log(p1.name); / / zhang SAN
console.log(p1.age); / / 19
// The constructor cannot be called
console.log(Perope.name); //Perope (can't actually be called here, but the constructor comes with a name property, so it prints Perope)
console.log(Perope.age); //undefined () cannot be called

// Try calling a static member
Perope.sayHello(); //hello
// The power object cannot be called
p1.sayHello(); / / an error
Copy the code

Conclusion: We can create members for constructors. Only members created inside the constructor using this. XXX have and can only be called by the instance, while member instances created using the constructor name

Constructor problem

Waste of memory

If you have any more than the same methods inside the constructor or property, if we want to create multiple objects, each object can have the same property and object, we will find that these methods and properties are independent in the group of (in memory), so if there is a lot of instance objects, then it will be very consumption of memory

// constructor
function Perope(name, age) {
  // Instance members: Only instance objects can be called
  this.name = name;
  this.age = age;
  this.sayName = function () {
    console.log(this.name); }}// Create an instance
var p1 = new Perope('a'.19);
var p2 = new Perope('b'.20);
// verify that p1 and p2 have the same sayname method
// The result is flase, so the method of these two objects will take up two pieces of memory. If there are too many instances, the same method will take up too much memory, resulting in memory waste
console.log(p1.sayName === p2.sayName);  //flase
Copy the code

The solution

  • plan1: Write methods in global functions, and then point to those functions inside the constructor.
    • Disadvantages: If we have a lot of methods, we need to create a lot of functions globally, which may cause some problems
  • plan2: Encapsulate a function inside an object and call the object’s methods inside the constructor
    • Cons: We still want to keep these properties and methods in our instance objects, which is simpler and easier to manage

A prototype object

Using prototype objects is a good way to avoid the memory waste caused by the previous constructors

Prototype object

Inside any function there is a pertoType property whose property value is an object

  • You can add methods or properties to the prototype object

  • The prototype constructor defaults to a cinstructor property that points to the function of the prototype object.

  • Instances created by isomorphic constructors contain a pointer (_proto_) that points to the prototype inside the constructor in the generated city

  • Instance objects have direct access to the members (properties and methods) of prototype objects

At work, we don’t use it_proto_To call a method or property, we’ll omit it_proto_Directly using instance. Method/property calls because_proto_Is not a standard property, but is generated automatically by the browser based on the syntax

Constructor waste memory solution – prototype object

  • Js specifies that each constructor has a prototype property that points to the constructor’s prototype object
  • Instance objects can directly or indirectly inherit methods or properties from the prototype

Therefore, we can define the shared properties and methods required by all instance objects on the prototype

// constructor
function Perope(name, age) {
  this.name = name;
  this.age = age;
}

// Add methods or properties shared by all instances to the prototype object
// Add the sayName method to the prototype
Perope.prototype.sayName = function () {
  // This calls to whom
  console.log(this.name);
}
// Add the sayAge method to the prototype
Perope.prototype.sayAge = function () {
  // This calls to whom
  console.log(this.age);
}

// Create two instance objects
var p1 = new Perope('a'.12),
  p2 = new Perope('b'.20);

// The method that executes the instance object, where _proto_ is omitted
p1.sayAge();
p2.sayName();

// Check whether p1 and p2 have the same reference to sayName
console.log(p1.sayName === p2.sayName); //true
Copy the code

At work, we can put all of the instance objects’ private properties or methods on the constructor and add public methods or properties to the prototype

Prototype chain

Why can instance objects call properties and methods on stereotypes?

When we call a method or property of an instance Object, we look inside the instance first. If the method or property does not exist in the Object instance, we look up the method or property of the constructor prototype, if we have not already looked up the method or property of the Object constructor prototype.

// constructor
function Perope(name, age) {
  this.name = name;
  this.age = age;
  // Create a property and a method on the constructor
  this.num = 2;
  this.sayName = function () {
    console.log('hello'); }}// Add methods or properties shared by all instances to the prototype object
// Add the sayName method to the prototype
Perope.prototype.sayName = function () {
  // This calls to whom
  console.log(this.name);
}
// Add the sayAge method to the prototype
Perope.prototype.sayAge = function () {
  // This calls to whom
  console.log(this.age);
}
// Add a property to the prototype that is already inside the constructor
Perope.prototype.num = 1;

// Create an instance object
var p1 = new Perope('a'.12);
SayName = sayName; sayName = sayName; sayName = sayName
p1.sayName();
// Call the instance object itself
console.log(p1.num);

SayAge (sayAge, sayAge, sayAge, sayAge)
p1.sayAge();

// We can see that
// When there is the same method on the instance object as on the prototype object, the instance method is called first, and the prototype method is not called
// When we call a method that is not on the instance, we look up to call a method on the prototype
Copy the code

To find the mechanism

Every time the code reads the properties of an object, a lookup is performed

  1. The instance object itself is searched first, and if the corresponding attribute is found in the instance, the attribute value is returned
  2. If not, continue to search for the prototype object to which the pointer points, search in the prototype object, if found, return the property value

Instance objects read and write prototype object members

Read:

  1. Self search, find return
  2. Unable to find the prototype, find return
  3. If the end of the prototype chain is not found, return undefined

Writing:

  • Value type member writes (Instance. Value type member = XXX) :
    • The stereotype object is masked, which means that properties or methods on the stereotype object cannot be modified, only themselves can be added or modified
  • Reference type member writes (Instance. Reference type member = XXX) : same as above
  • Complex type member modification (Instance. Member. Xx = XXX) :
    • Now they look for members, find to modify themselves, can not find the prototype chain, find the value of the prototype chain to modify, can not find the error
// constructor
function Perope(name, age) {
  this.name = name;
  this.age = age;
}

// Add the sayName method to the prototype
Perope.prototype.sayName = function () {
  // This calls to whom
  console.log(this.name);
}
// Add the sayAge method to the prototype
Perope.prototype.sayAge = function () {
  // This calls to whom
  console.log(this.age);
}
// Add an object to the prototype
Perope.prototype.me = {
  num: 1
};
// Add a value attribute to the stereotype
Perope.prototype.sex = 'nan';

// Create an instance
var p1 = new Perope('zhangsan'.19);

// Try to modify the method on the prototype
// Modify the reference
p1.sayAge = function () {
  console.log('1111');
}
/ / modify the value
p1.sex = 'nv';
// Modify the complex type member
p1.me.num = 2;

// Print an instance
// The sayAge and sex attributes are added to p1, and the values of the attributes are the same as those we are trying to modify, indicating that we cannot modify the values or references on the prototype
// We also find that the value of p1.me.num on the prototype is 2, so we can successfully modify the complex type member without creating new attributes on the instance
console.log(p1);
Copy the code

Simpler prototype syntax

Prototype = {}; prototype = {};

One caveat, however, is that modifying the constructor directly will cause it to be lost. We will print to find that we point to Object, so we need to manually point a constuctor to the correct constructor

// constructor
function Perope(name, age) {
  this.name = name;
  this.age = age;
}

// // Add the sayName method to the prototype
// Perope.prototype.sayName = function () {
// // the this who call in here points to who
// console.log(this.name);
// }
// // Add a value attribute to the stereotype
// Perope.prototype.sex = 'nan';


// Add the optimized writing of the prototype method above
Perope.prototype = {
  // Manually add constructor and point to the corresponding constructor
  constructor: Perope,
  // Add attributes and methods directly inside the object
  sayName: function () {
    console.log(this.name);
  },
  sex: 'nan'
}
var p1 = new Perope('zhangsan'.1);
console.log(p1);
Copy the code

Suggestions for using prototype objects

When defining constructors, we can set them separately according to the function of the members:

  • Private members: Generally non-function members placed inside the constructor
  • Shared members: Typically functions, placed in prototypes

If you reset Prototype remember to correct the constructor reference

A prototype object with a built-in constructor

All functions have a Prototype property object, and the built-in constructor in JS also has a Prototype property:

  • Object.prototype
  • Function.prototype
  • Array.prototype
  • String.prototype
  • Number.prototype
  • .

Add methods to the built-in constructor object prototype

  1. It is not allowed to change prototype objects directly using object literals, because the JS built-in is protected from direct changes
  2. Methods can be added using the drip-call method, but we generally don’t allow methods on built-in objects in our work

Case study: Random squares

Requirement: in a stage, let 10 small square randomly change position, after refreshing the small square color can be discernible, do not refresh the small square color unchanged

  • Here we’re doing object-oriented programming, thinking of each little square as an object, so we need to customize the constructor, use the constructor to construct the little square, and the little square should have a way to render itself into the HTML structure, and also a way to modify its position
  • In addition, we need a set of utility functions that can be written inside an object, which needs to have methods that can generate random numbers and colors;
<! DOCTYPEhtml>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <! -- Introducing CSS styles -->
  <link rel="stylesheet" href="./css/index.css">
</head>

<body>
  <! Create a stage that holds small squares -->
  <div id="box" class="box"></div>
  <! -- Introduce javascript code -->
  <script src="./js/tools.js"></script>
  <script src="./js/block.js"></script>
  <script src="./js/index.js"></script>
</body>

</html>
Copy the code
/* Clear style */
* {
  margin: 0;
  padding: 0;
}

/* Set stage positioning, width and height, background color */
.box {
  position: relative;
  width: 800px;
  height: 800px;
  background: #ccc;
}

/* Sets the absolute position of small squares inside the stage */
.box span {
  position: absolute;
}
Copy the code
// Get the element
var box = document.getElementById('box');
// Create an array to hold the created instance objects
var blocks = [];
// Loop 10 times to create a small cube object
for (let i = 0; i < 10; i++) {
  // Create an instance object
  var me = new Block(box, {
    // Pass in a random color argument
    backgroundColor: Tools.getColor()
  });
  // Execute the render method of the created instance object
  me.toHtml();
  // Add the created instance object to the array
  blocks.push(me);
}
// Iterate over all the instance objects in the array
for (let i = 0; i < blocks.length; i++) {
  // Create a timer that executes the random position method in the instance object every 1 second
  setInterval(function () {
    blocks[i].chagePosition();
  }, 1000)}Copy the code
// Create a constructor to build a small box
// Argument 1: stage element for small squares
// Argument 2: the style property object for the small box
function Block(father, obj) {
  // Avoid user not passed boj for record
  var obj = obj || {};
  // Create all the attributes needed for the cubes
  this.width = obj.width || 20;
  this.height = obj.heigth || 20;
  this.backgroundColor = obj.backgroundColor || 'red';
  this.top = obj.top || 0;
  this.left = obj.left || 0;
  // Create the stage property, get the stage (this must get, otherwise it will show undefined)
  this.father = father;
}

// Prototype object modification
Block.prototype = {
  // Manually point to the Block constructor
  constructor: Block,
  // Add the prototype method: render
  toHtml: function () {
    // Create element nodes and pass them to the constructor for use by other methods
    this.me = document.createElement('span');
    // Modify the inline style of the element style
    this.me.style.width = this.width + 'px';
    this.me.style.height = this.height + 'px';
    this.me.style.backgroundColor = this.backgroundColor;
    this.me.style.top = this.top + 'px';
    this.me.style.left = this.left + 'px';
    // Insert the box at the bottom of the parent element
    this.father.appendChild(this.me);
  },
  // Prototype method: random position
  chagePosition: function () {
    // Change your left attribute (use Tools random number (1- stage width/small square width - 1) * small square width) to avoid small square overlap
    this.left = Tools.getNumber(0.this.father.clientWidth / this.width - 1) * this.width;
    // Change the value of top
    this.top = Tools.getNumber(0.this.father.clientHeight / this.height - 1) * this.height;
    // Modify the location properties of small squares
    this.me.style.top = this.top + 'px';
    this.me.style.left = this.left + 'px'; }}Copy the code
// Create a tool object to prevent random number methods
var Tools = {
  // Object method: Get the random number between two specified numbers, including these two numbers
  getNumber: function (min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1) + min);
  },
  // Returns a random color value
  getColor: function () {
    return 'rgb(' + this.getNumber(0.255) + ', ' + this.getNumber(0.255) + ', ' + this.getNumber(0.255) + ') '; }}Copy the code