This is the fifth day of my participation in Gwen Challenge

Object-oriented programming

After learning JS advanced and ES6, I will learn object-oriented programming. I have come into contact with this idea when learning ES6 and Canvas before, and I feel that I still need to learn it in depth. This part involves a lot of things in the prototype chain, which is still very good as a review!

ES5Object oriented in

Object – oriented programming (OOP) is flexible, reusable and highly modular.

  1. An object is an abstraction of a single object

  2. An object is a container that encapsulates corresponding properties and methods. Properties are the state of the object, and methods are the behavior of the object (the task accomplished).

The constructor instantiates the object

There is no concept of class classes in ES5, so object orientation is based on constructors and prototype chains,

Note: The first letter of the constructor’s name is capitalized

The characteristics of

  1. Function body usethisKeyword that represents the object instance to be generated
  2. Generate an object that must be usednewKeyword instantiation
function Dog() {
	this.name = name;
	this.age = age;
}
var dog1 = new Dog('dw'.10)
Copy the code

If the new keyword is not used, the result will be undefind because the function has no return value

instanceofThe use of the

The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object. Return trueorfalse

Use instanceof to determine if the current object is instantiated. If this is instantiated, it points to the instantiated object, which is Person, otherwise, as a normal function, this points to the window

function Person(name, age){
	if(this instanceof Person){
		// this refers to the current instance with the external keyword new
		this.name = name;
		this.age = age;
	}else{
		// This refers to window without the new keyword
		return new Person(name,age);
}
Copy the code

newInternal principles of commands

  1. Create an empty object
  2. constructionalthis, inheriting function prototypes
  3. letthisAn object instance that points to the constructor and executes the constructor content to add properties and methods to the new object
  4. Return this object
var obj = {}// Create an empty object
obj.__proto__ = Person.prototype;// Inheritance scope
Person.call(obj,)// Change this pointer
return obj // Return the object
Copy the code

constructorattribute

Each object automatically has a constructor attribute when it is created

Constructor is a property on the object __proto__ (or, if the object is a function, on its prototype) and usually points to the function that generated the object, that is, a reference to the constructor

obj.constructor === Obj
Copy the code

Pros and cons of using constructors to create objects

  1. Code redundancy
  2. The ability to share internal properties and methods

A prototype object

function Foo(){};
var foo = new Foo();
Copy the code

Prototype object: foo.prototype

Instance objects: Foo is an instance object. Each prototype object has a __proto__, and each instance object has a constructor property, which is inherited by inheritance and points to the current constructor foo

Constructor: the function used to initialize the newly created object. Foo is the constructor that automatically gives the constructor a property, prototype, that points to the prototype object of the instance object

The relationship between prototype objects, instance objects, and constructors

function Foo(){}
var foo = new Foo()
Copy the code

prototypeThe role of attributes

Inheritance mechanism: Through the prototype object (prototype) inheritance

The purpose of a stereotype object is to define properties and methods shared by all instance objects

Foo.prototype.name = 'ljc';
Copy the code

Prototype chain

All objects have their own prototype objects

Prototype chain: Prototype of object => prototype of prototype => prototype of prototype => NULL

All objects inherit properties and methods from Object.prototype

The js engine will first look for the properties and methods of the Object itself. If it can’t find the Object, it will look for the prototype Object. If it can’t find the prototype Object, it will look for the prototype Object

Note: Once we modify the constructor’s prototype object, we also modify the constructor property to prevent reference problems

Method to create a new object with an array

function MyArray(){};// constructor
MyArray.prototype = Array.prototype;// Copy the array prototype object, get the method
MyArray.prototype.constructor = MyArray;// Change the constructor direction
var arr = new MyArray();// instantiate the object
Copy the code

N ways to create an object

1. Object literals

  1. literal
var Person = { name: 'ljc' }
Copy the code
  1. newThe keyword
var obj = new Object(a); obj.name ='ljc';
console.log(obj);
Copy the code
  1. Object. The create (Object)
var a = {
	getName:function(){
		console.log('ljc'); }}var b = Object.create(a);
b.getName();
Copy the code

Disadvantages: Code redundancy

2. Factory mode

Advantages: Ability to create multiple similar objects

function createObj(name,age) {
	var o = new Object(a);// Create an object
    // Add attributes and methods
	o.name = name;
	o.age = age;
	o.sayName = function() {
		console.log(this.name);
	}
    // Return the object
	return o
}
var obj = createObj('ljc'.19)// Each call returns an object
Copy the code

Disadvantages: All constructor directions are the same and do not solve the object recognition problem

3. Constructor pattern

function Person(name,age){
	this.name = name;
	this.age = age;
	this.sayName = function(){
		console.log(this.name); }}var man = new Person('ljc'.19);
var woman = new Person('dw'.18);
Copy the code

The legacy of the factory pattern is solved by using the new keyword externally to bind properties and methods to the corresponding objects through this

Disadvantages: Each object has a sayName method that performs the same function, but still occupies different memory space and wastes memory resources

  1. The constructor extends the schema
function Person(name,age){
	this.name = name;
	this.age = age;
	this.sayName = sayName;
}
function sayName(){
	console.log(this.name);
}
Copy the code

The problem of memory waste is solved by defining the sayName method as a global function

Disadvantages: pollution global space

  1. Parasitic constructor pattern
function createObj(name,age) {
	var o = new Object(a);// Create an object
    // Add attributes and methods
	o.name = name;
	o.age = age;
	o.sayName = function() {
		console.log(this.name);
	}
    // Return the object
	return o
}
var obj = new createObj('ljc'.19)
Copy the code

A combination of the factory pattern and the constructor pattern: create a function, instantiate an object internally and return the object, and instantiate the object externally using new

Disadvantages: The instanceof operator and prototype attribute are meaningless because constructors are not used

  1. Secure constructor pattern
function Person(name){
	var a = 10;
	var obj = new Object(a); obj.sayName =function(){
		console.log(a);
		console.log(name);
	}
	return o;
}
var p1 = Person('ljc');
p1.sayName();
Copy the code

There are no public attributes, and its methods don’t refer to this. Name is a private property inside the function, sort of like a closure. P1 is called a secure object

Disadvantages: The instanceof operator and prototype attribute are meaningless because constructors are not used

4. Prototyping

Bind attribute methods to Prototype for sharing

Note: You need to change the constructor direction

function Person(){}
Person.prototype = {
	constructor: Person,
	name: 'ljc'.age: 19.friends: ['dw'.'xy'].sayName:function(){
		console.log(this.name); }}var me = new Person();
var you = new Person();
Copy the code

Each object instantiated by Person inherits the prototype of the function

Disadvantages: When we modify the properties of one object, the properties of the other object are also modified

me.friends.push('jc');
console.log(you.friends);//["dw","xy","jc"]
Copy the code

5. Combination mode

The most common pattern for creating custom objects

function Person(name,age){
	// Customize the current object's own properties
	this.name = name;
	this.age = age;
	this.friends = ['dw'.'xy'];
};
// Customize the public method
Person.prototype = {
	constructor: Person,
	sayName: function(){
		console.log(this.name); }}var wo = new Person('wo'.18);
var you = new Person('you'.20);
Copy the code

The problem of state sharing of prototype mode is solved by defining private attributes inside functions and inheriting references of common methods through prototypes

Multiple ways of prototype chain inheritance

All properties and methods in the prototype object can be shared by the instance

Prototype chain inheritance

Treat the properties and methods of a parent object as the properties and methods of a child object’s prototype object by overriding the prototype object

function Animal(){
	this.name = 'alex';
	this.colors = ['red'.'green'.'blue'];
}
Animal.prototype.getName = function(){
	return this.name;
}// Add method
function Dog(){};
Dog.prototype = new Animal();// Inherit animal from dog
Dog.prototype.constructor = Dog;/ / points to the dog
var d1 = new Dog();
var d2 = new Dog();
Copy the code

Existing problems:

  1. Once an instance attribute in a parent class is assigned to the stereotype attribute of a subclass, those attributes are all shared attributes of the subclass. If you change one, all the others will be modified
  2. When instantiating a child type, you cannot pass arguments to the constructor of the parent type

Inheritance by constructor

By calling the parent constructor inside the subclass constructor, the problem of inheritance in prototype chain is solved

Using the call keyword, change this of the current function to refer to the current instance object

The new procedure refers to this to the current instance object, so this inside the constructor refers to the current instance object

function Animal(name){
	this.name = name;
	this.colors = ['red'.'green'.'blue'];
}
Animal.prototype.getName = function(){
	return this.name;
}
function Dog(name){
	Animal.call(this,name);
}
var d1 = new Dog('huang');
var d2 = new Dog('little red');
Copy the code

** There are problems: ** the parent class defined by the == shared method == cannot be inherited by subclasses, only attributes

Combination of inheritance

The combination of prototype chain inheritance and constructor inheritance brings together the advantages of both

function Animal(name) {
	this.name = name;
	this.colors = ['red'.'green'.'blue'];
}
Animal.prototype.getName = function() {
	return this.name;
}
function Dog(name) {
	Animal.call(this, name);// Use constructor inheritance
}
Dog.prototype = new Animal();// Prototype chain inheritance
Dog.prototype.constructor = Dog;
var d1 = new Dog('huang');
var d2 = new Dog('hong');
Copy the code

Using the method of stereotype chain inheritance (overriding the stereotype object), the parent class’s shared methods are inherited, and the parent class constructor is called in the subclass constructor, so that the value of one side can be modified without affecting the value of the other side

** Has a problem: ** Calls the parent constructor twice in any case

Parasitic combinatorial inheritance

Use the object. create method to pass the parent class’s prototype Object to the child class’s prototype Object

Change line 11 in composite pattern inheritance to the following

Dog.prototype = Object.create(Animal.prototype)
Copy the code

Multiple inheritance

Copy prototype objects using object. assign method to achieve multiple inheritance (mixed with technical mixins)

The object.assign () method is used to assign the values of all enumerable properties from one or more source objects to target objects. It will return the target object.

Me.prototype = Object.create(Person.prototype);
Object.assign(Me.prototype, Parent.prototype);
Copy the code

In this way, the prototype object of the parent constructor is copied to its own constructor, and the prototype of multiple parent functions is bound to a child element

Static methods of Object

1.Object.keys():

The argument is an object, the return is an array, enumerable only return, equivalent to for… In circulation

let a = {
    name:'ljc'.age:19
}
let arr = ['l'.'j'.'c'];
console.log(Object.keys(arr));/ / / "0", "1", "2"]
console.log(Object.keys(a));// ["name", "age"]
Copy the code

Note: An array is also an object that can be passed in as an argument and returns the array index

2.Object.getOwnPropertyNames()

Takes an object as an argument and returns an array containing all the property names of the object itself, including non-enumerable properties

let arr = ['l'.'j'.'c'];
console.log(Object.getOwnPropertyNames(arr));// ["0", "1", "2", "length"]
Copy the code

3.Object.getPrototypeOf():

The argument is an object that returns the prototype of the object and is the standard way to get the prototype object

function Fn() {}
let f1 = new Fn();
console.log(Object.getPrototypeOf(f1) === Fn.prototype);//true
Copy the code

Equivalent to the constructor’s Prototype method

Note: The prototype for the empty Object is Object.prototype

console.log(Object.getPrototypeOf({}) === Object.prototype);//true
Copy the code

Note: The Function prototype is function.prototype

console.log(Object.getPrototypeOf(foo) === Function.prototype)//true
Copy the code

4.Object.setPrototypeOf():

Take two parameters, the first is an existing object, the second is a prototype object, and the second is a prototype of the first

var a = {};
var b = {
    x: 1
};
Object.setPrototypeOf(a, b);// Use b as a prototype of A
console.log(a.x);/ / 1
console.log(Object.getPrototypeOf(a))// {x: 1}
Copy the code

simulationnewThe keyword

function F(){
	this.foo = 'foo';
}
var f = Object.setPrototypeOf({},F.prototype);// Create an empty object, inherit the prototype, and return the object
F.call(f);// Change this pointer
console.log(f);// F {foo: "foo"}
Copy the code

The Object. SetPrototypeof method can simulate the implementation of new internal principle

5.Object.create():

Create a new object and use the existing object (the argument passed in) to provide the __proto__ of the newly created object, that is, use this argument as the prototype of the new object

var A = {
    say :function() {
        console.log('ljc'); }}var B = Object.create(A)
B.say();// ljc
Copy the code

The method also has a second argument, a somewhat complicated MDN link

More methods on Object

1.valueOf():

Returns the original value of the specified object.

// Function: returns the Function itself
function foo(){}
console.log( foo.valueOf() === foo );   // true
// Array: Returns the Array object itself
var array = ["ABC".true.12, -5];
console.log(array.valueOf() === array);   // true
Copy the code

JavaScript automatically calls it when it encounters an object with a raw value to expect.

We can customize this method based on such features to achieve the desired operation

var obj = new Object()
obj.valueOf = function(){
	return 2;
}
console.log(obj.valueOf() === obj);
console.log(1 + obj);// 1[object Object] ------> 3
Copy the code

Valueof is a method that belongs to the Object prototype Object. The hierarchy of Object.valueof takes precedence over the methods in the prototype Object, so our custom Valueof method is called first

2.toString():

Returns a string representing the object.

var o = new Object(a); o.toString();// returns [object Object]
Copy the code

Override defaulttoStringmethods

function Dog(name,breed,color,sex) {
  this.name = name;
  this.color = color;
}
var theDog = new Dog("Gabby"."chocolate");
Dog.prototype.toString = function dogToString() {
 var ret = "Dog " + this.name + " is " + this.color + "" ;
 return ret;// 'Dog GAbby' is chocolate
}
Copy the code

Note: In each different data type, we define our own toString method

3.toLocaleString()

Returns a string representation of the object in a form dependent on the user locale

  • Array:Array.prototype.toLocaleString()
  • Number:Number.prototype.toLocaleString()
  • Date:Date.prototype.toLocaleString()

These feelings are a little unclear, this part comes from the MDN documentation

4.isPrototypeOf()

Used to detect whether an object exists on the prototype chain of another object

The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object

Difference: inPrototypeOf determines whether the object is the child of another object, instanceof determines whether the instance object was created by the constructor

5.hasOwnProperty()

Method returns a Boolean value indicating whether the object has the specified property in its own property

o = new Object(a); o.prop ='exists';
o.hasOwnProperty('prop');  
Copy the code

Note: Only its own properties are true, inherited properties return false,

6.getOwnPropertyDescriptor()

You can get description properties using the getOwnPropertyDescriptor property, you can only get your own properties, not inherited properties

Writable: indicates whether it is writable

Enumerable: Whether it is enumerable

Different: Specifies whether the system can be configured, for example, deleted

Set: a setter function for a property, or undefined if there is no setter. The function will only accept the new value assigned to the property by the argument.

Get: serves as the getter for this property, undefined if there is no getter. The value returned by the function will be used as the value of the property.

var obj = {
    name:'ljc'
}
console.log(Object.getOwnPropertyDescriptor(obj,'name'));
//{value: "ljc", writable: true, enumerable: true, configurable: true}
Copy the code

7.propertyIsEnumerable()

Returns a Boolean value indicating whether the specified property is enumerable

var arr = [1.2.3];
console.log(arr.propertyIsEnumerable('length'));//false
Copy the code

Note: Only the attributes of the instance object can be judged, not the inherited attributes, otherwise false

8.defineProperty()

Define a new property directly on an object, or modify an existing property of an object and return the object.

By reference

Object.defineProperty(Attribute object, attribute name, attribute description object)Copy the code

The sample

let obj = {};
Object.defineProperty(obj, "key", {
  enumerable: false.configurable: false.writable: false.value: "ljc"
});
console.log(obj)// {key: "ljc"}
Copy the code

9.defineProperties()

Method directly defines new properties or modifies existing properties on an object and returns the object. Multiple attributes can be defined at once

The sample

var obj = Object.defineProperties({},{
	p1: {value:123.enumerable:true
	},
	p2: {value:"ljc".enumerable:false
	},
	p3: {get:function(){
			return this.p1 + this.p2;
		},
		enumerable:true.configurable:true}})console.log(obj);// {p1: 666, p2: "ljc"}
console.log(obj.p1);/ / 666
Copy the code

The p2 property is lightened because it is not enumerable

Note: Once you define the get function, you cannot also define the value attribute, otherwise an error will be reported, and you cannot set the writable attribute

Note: if this method is called and an empty object is passed, all values will be set to false

var obj4 = Object.defineProperty({},'foo'{});Copy the code

When the property value is not writable, no errors are reported and no changes are made

10. Attribute description object

A couple of points

If enumrable is set to false, the following three operations generally do not fetch this property

  • for... in
  • Object.keys()
  • JSON.stringify()

Note: You can get inherited attributes, although you cannot get your own


  • If configurable to false, the property description object value, writable, enumrable, configurable cannot be modified

  • Writable, true to false will allow this

  • The value property can be modified without any additional information if either writable or 64x is true

11. Accessors

The get method, which is automatically called when a property is obtained

The set method, which is automatically called when a property is modified, takes one parameter

let obj = {
    num: 2.get a() {
        return 'I'm being called. My value increases.' + ++this.num
    },set a(value) {
        console.log('I've been changed.'); }}console.log(obj.a);// I am called and my value is increased by 3
obj.a = 2;// I have been changed
Copy the code

So much for object orientation!


In ES6, we added the class keyword and some related properties to improve the readability of object-oriented code. The new class method makes the writing of object prototypes clearer and more like the syntax of object-oriented programming, so class is just a syntax sugar. All of it can be implemented through object prototyping in ES5