1, Object oriented
1. Succession
As long as the method definition is placed in the constructor, function will be executed every time new, which will repeatedly create multiple copies of the same function, resulting in a waste of memory. If it is found that multiple sub objects need to use the same function and attribute values in the future, inheritance can be used to solve them.
Members in the parent object and child objects can be used directly without repeated creation, just like using their own members, which is inheritance. Inheritance in js is realized through prototype objects, which are special parent objects that save common attribute values and methods for all child objects. When multiple sub objects need to use the same function and attribute values, the same function and attribute values can be defined in the prototype object.
Prototype object: you don't have to create it yourself. When defining the constructor, the program automatically gives us an empty prototype object. Each constructor has its own attribute prototype, which points to its paired prototype object, the constructor. Prototype.
Four functions of new |
1. Create a new empty object and wait |
2. Let the child object inherit the prototype object of the constructor (inheritance only) |
3. Call the constructor, replace this with a new object, and add the specified attributes to the new object by forced assignment |
4. Return the address of the new object |
The second step of new automatically lets the newly created child object inherit the prototype object of the constructor. New automatically adds _tothe child object_ proto_ _ Property that points to the prototype object of the constructor.
When adding new common properties and methods to the prototype object, you can only force the assignment:
Constructor. prototype. Common method = function() {...} |
Constructor. prototype. Common attribute = attribute value |
After adding a new attribute or method, when accessing the member of the object with a sub object, the js engine first finds its own attribute in the sub object; If there is no child object, the js engine will automatically delay __ proto_ _ Property to find the parent element. If the desired attribute or method is found in the parent element, it is called as the method accessing the child object.
Example: save the method shared by all child objects into the constructor
<script> // Constructor function Student(sname, sage) { this.sname = sname; this.sage = sage; } // Forcibly add a method intr shared by all child objects to the prototype object of student type Student.prototype.intr = function () { console.log(`My name is ${this.sname},I this year ${this.sage}year`); } // Repeatedly create multiple objects with the same structure but different contents with the constructor var lilei = new Student("Li Lei", 45); var hmm = new Student("Mei Mei Han", 30); console.log(lilei); console.log(hmm); lilei.intr(); hmm.intr(); console.log(lilei.__proto__ == Student.prototype); //true indicates that the prototype object is the parent of the child element console.log(hmm.__proto__ == Student.prototype); //true </script>
· Self owned attribute and common attribute
Self owned attribute: it is saved in the child object and only belongs to the self owned attribute of the current child object; |
Common attribute: it is saved in the parent object (prototype object) and belongs to the common attribute of multiple child objects; |
(1) When getting the property value, it is available without difference: sub object. Property name. If the js engine finds that the attribute to be used is not in the child object, it automatically delays __ proto_ _ Property continues to find the property to use from the parent object.
(2) Modify attribute value
Own attribute: | Sub object. Attribute name = attribute value; |
Common attributes: | Correct method | Wrong method |
Constructor. prototype. Common attribute = new value | Child object. Common attribute = new value | |
Common properties, which must be modified with prototype objects | This method not only does not modify the common property in the prototype object, but also adds a self owned property with the same name to the current sub object. Since then, this sub object can no longer be synchronized with other sub objects in the use of this property! |
Example: add a common class name attribute for all students and modify it
<script> function Student(sname, sage) { this.sname = sname; this.sage = sage; } Student.prototype.className = "Class 1 and class 2 of junior high school"; var lilei = new Student("lilei", 11); var hmm = new Student("hmm", 12); // Modify own attribute lilei.sname = "zhangsan"; console.log(lilei); console.log(hmm); console.log(lilei.className, hmm.className); // One year later, the two students upgrade together (modify common attributes) // 1. Error mode // lilei.className = "class 2, grade 2 of junior high school"; // This method will not modify the common attributes in the prototype object, but will add a self owned attribute with the same name to the current sub object, so that the sub object cannot continue to be synchronized with other sub objects. // 2. In the correct way, the prototype object must be modified Student.prototype.className = "Class 2, grade 2, junior high school"; console.log(lilei.className, hmm.className); </script>
· Prototype object of built-in type
The built-in type is the type specified in the ES standard, which has been implemented by the browser and can be used directly. It includes eleven kinds of String, Number, Boolean, Array, Date, RegExp, Error, Function, Object, math (not a type, but a {} Object), global (global scope Object, which is replaced by window in the browser).
Each type must have two parts: constructor, which is responsible for creating sub objects of this type; Prototype object, which is responsible for saving common attribute values and method definitions for all sub objects of this type. In addition to Math and global, you can also create sub objects through new.
To see which API s are available in this type, you can use -- type name. prototype --.
If we often use a function, but it is not provided in the prototype object, we can customize a function and save it to the prototype object.
Constructor. prototype. New method = function() {...} |
Example: adding a summation method to an array type
<script> var array1 = [1, 2, 4, 5, 8, 8]; var array2 = [125, 48, 48, 478, 2584]; // Create custom function Array.prototype.sum = function () { console.log("Call custom function sum"); // Array summation routine // 1. Define variables to temporarily maintain the summed value var sum = 0; // 2. Traverse array elements for (i = 0; i < this.length; i++) { // 3. Accumulate the traversed element values sum += this[i]; } // 4. Return accumulation result return sum; } // Call sum console.log(array1.sum()); console.log(array2.sum()); </script>
·Prototype chain
Prototype chain is a chain structure formed by level-by-level inheritance of multi-level parent objects. It stores all the attributes and methods available to an object, controls the use order of attributes and methods, and adopts the proximity principle. The child level is first followed by the parent level.
<script> function Student(sname, sage) { this.sname = sname; this.sage = sage; } // Add a toString method to the Student prototype object Student.prototype.toString = function () { // Here this refers to a child object of a student's type before the point where toString() will be called in the future return `{sname:${this.sname},sage:${this.sage}}`; } var lilei = new Student("lilei", 12); var arr = [1, 2, 3]; var now = new Date(); console.log(lilei.toString()); console.log(arr.toString()); console.log(now.toString); </script>
2. Polymorphism
Polymorphism means that the same function shows different states in different situations, including overloading and rewriting.
overload | The same function inputs different parameters and executes different logic. |
override | Define a self owned member in the child object with the same name as the member in the parent object. When an individual member inherited from the parent object is not easy to use, you can define a member with the same name in the child object to override the member with the same name in the parent object. |
3. Custom inheritance
(1) There are two ways to replace the parent object of only one object:
Sub object_ proto_ _= New parent | Not recommended |
Object.setprototypeof (child object, new parent object) | recommend |
//Example: replacing the parent of an object <script> function Student(sname, sage) { this.sname = sname; this.sage = sage; } var lilei = new Student("Li Lei", 11); var hmm = new Student("Mei Mei Han", 12); var father = { money: 1000000000000, car: "infiniti" } // 1. Replace the parent object of only one object // Change the inheritance parent object of hmm to father // hmm.__proto__ = father;// Not recommended Object.setPrototypeOf(hmm, father); //recommend console.log(hmm.money, hmm.car); console.log(lilei.money, lilei.car); console.log(lilei); console.log(hmm); </script>
(2) To batch replace the parent object of multiple child objects, you only need to replace the prototype attribute of the constructor, but you must replace it before creating the child object!
//Example: batch replacement of parent objects of two child objects <script> function Student(sname, sage) { this.sname = sname; this.sage = sage; } var father = { money: 1000000000000, car: "infiniti" } // 2. Batch replacement of parent objects of multiple child objects // The prototype object of the constructor must be replaced before the child object is created Student.prototype = father; var lilei = new Student("Li Lei", 11); var hmm = new Student("Mei Mei Han", 12); console.log(hmm.money, hmm.car); console.log(lilei.money, lilei.car); console.log(lilei); console.log(hmm); </script>
2, ES5 (ECMAScript version 5)
1. Strict mode
There are many widely criticized defects in the old js. The strict mode is a new operation mechanism that requires stricter requirements than the old js operation mechanism. In the future, all codes in the enterprise should run in the strict mode. To enable strict mode, simply add the following at the top of the current snippet: "use strict"; Just. The strict model has four new provisions:
a: It is forbidden to assign values to undeclared variables; In the old js, if you forcibly assign a value to an undeclared variable, you will not report an error. Instead, you will automatically set the variable globally, which will cause global pollution. In strict mode, forcibly assigning values to undeclared variables will report errors, which reduces the global pollution caused by writing wrong variable names!
Example: assign a value to an undeclared local variable
<script> function send() { var gf; // Suppose you accidentally write the wrong variable name qgf = "Tonight 308, w84u"; //Direct error qgf is not defined console.log(`Girlfriend received ${gf}`); } send(); console.log(`In the global: ${qgf}`); </script>
The strict mode is not used. The following is printed. The message originally intended to be sent to the "girlfriend" is sent to the whole world, but the system does not report an error.
Enable strict mode and add "use" in the first line of the code snippet strict";
<script> // Enable strict mode "use strict"; // Assignment to undeclared variables is prohibited function send() { var gf; // Suppose you accidentally write the wrong variable name qgf = "Tonight 308, w84u"; //Direct error qgf is not defined console.log(`Girlfriend received ${gf}`); } send(); console.log(`In the global: ${qgf}`); </script>
Print it as follows. At this time, an error is reported directly, so that we can find the problems in the program and modify them.
b. Silent failure is upgraded to error; Silent failure means that the program does not run successfully, but there is no error, which is extremely unfavorable to debugging the program. Strict mode: most silent failures will be upgraded to error. give an example:
<script> // Silent failure upgrade to error var eric = { aid: 1001, sanme: "Stark " } // The eid attribute is set to read-only here Object.defineProperty(eric, "eid", { writable: false }) // Attempt to tamper eric.eid = 1002; console.log(eric); </script>
Print as follows: even if the eid is set to read-only, the attribute value is still modified without error.
After starting strict mode, print as follows:
c. This in ordinary function calls no longer refers to window, but to undefined. In old js, this in ordinary function calls refers to window by default, which is very easy to cause global pollution. After strict mode is enabled, this in ordinary function calls points to undefined instead of window, which can prevent global pollution caused by wrong use of this. give an example:
<script> // Enable strict mode "use strict"; // this in ordinary function calls no longer refers to window, but to undefined function Student(sname, sage) { console.log(this); this.sname = sname; //Cannot set property 'sname' of undefined this.sage = sage; } var lilei = new Student("Li Lei", 12); // Suppose you forget to write new var hmm = Student("Mei Mei Han", 13); console.log(lilei); console.log(hmm); console.log(window); </script>
d. Disabled arguments.callee, arguments.callee; Is to obtain a special keyword (recursion) of the current function itself in a function. Write the current function name in the function. Once the external function name changes and the internal function name forgets to be modified, the program immediately reports an error, resulting in tight coupling. Therefore, use arguments.callee in the function instead of the written function name. At run time, the current function itself is automatically obtained (loosely coupled).
Moreover, the amount of recursive repeated calculation is too large and the efficiency is very low. If the recursive call seriously affects the performance of the program, it is necessary to use a loop instead of recursion. Example: calculate the nth number of Fibonacci sequence using recursion and loop respectively
//Recursive mode <script> // arguments.callee is disabled // Fibonacci sequence // The first two numbers are both 1. Starting from the third number, each number is the sum of its adjacent first two numbers function f(n) { if (n < 3) { return 1; } else { return arguments.callee(n - 1) + arguments.callee(n - 2); } } console.log(f(10));//55 </script>
//Cycle mode <script> function f(n) { if (n < 3) { return 1; } else { var f1 = 1, f2 = 1, fn; for (var i = 3; i <= n; i++) { fn = f1 + f2; f1 = f2; f2 = fn; } return fn; } } console.log(f(10)); //55 </script>
Supplement: 4 kinds of this
(1)obj.fun() this in fun refers to the obj object before (who calls who);
(2)new Fun() this in fun refers to the new object created by new;
(3) fun() or (function() {...}) () or callback function thisz refers to windozw by default;
(4) this in the prototype object refers to a child object (who calls who) before calling the common function in the future.
Links to previous JavaScript basic blog posts:
Fundamentals of JavaScript (I)
Fundamentals of JavaScript (II)
Fundamentals of JavaScript (III)