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!
ES5
Object oriented in
Object – oriented programming (OOP) is flexible, reusable and highly modular.
-
An object is an abstraction of a single object
-
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
- Function body use
this
Keyword that represents the object instance to be generated - Generate an object that must be used
new
Keyword 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
instanceof
The 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
new
Internal principles of commands
- Create an empty object
- constructional
this
, inheriting function prototypes - let
this
An object instance that points to the constructor and executes the constructor content to add properties and methods to the new object - 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
constructor
attribute
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
- Code redundancy
- 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
prototype
The 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
- literal
var Person = { name: 'ljc' }
Copy the code
new
The keyword
var obj = new Object(a); obj.name ='ljc';
console.log(obj);
Copy the code
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
- 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
- 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
- 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:
- 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
- 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
simulationnew
The 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 defaulttoString
methods
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