I. Objects of JS
1.1 Several ways to create objects
1.1.1 Create Objects by Literal Quantity
In js, a pair of {} is actually an object
var person = { name: "tom", age: 23, read: function () { console.log(name, ": read book") } }
1.1.2 via the constructor of the system
Create an empty object through the system's constructor, then use the js dynamic language feature, if an object does not have an attribute or method, click and attach the value
var person2 = new Object() person2.name = "jerry" person2.age = 23 person2.say = function () { console.log(person2.name, ": say hello") }
1.1.3 via a custom construction method
Custom constructors are typically capitalized functions
function Person(name, age, sex) { this.name = name this.age = age this.sex = sex this.say = function () { console.log(this.name, " :say hello") } } // When creating objects, use the new keyword p = new Person("tom", 23, "man") console.log(p instanceof Person)
Custom construction methods create objects through the following steps
- Open up space
- Set this as the current object
- Initialization properties and methods
- Return this
1.1.4 Factory Mode Creation Objects
function Person(name,age,sex) { // new Object as current return value var obj = new Object() obj.name = name obj.age = age obj.sex = sex obj.say = function () { console.log(this.name," :say hello") } // Manually Return Objects return obj } // Factory mode creates objects without using the new keyword var p = Person("tom",23,"man") console.log(p instanceof Person) // false
1.2 Constructors and Instance Objects
Take the following example:
// Relationships between constructors and instances function Person(name) { this.name = name this.say = function () { console.log(this.name," :say hello") } } // Object p was created with a custom constructor, Person var p = new Person("tom") console.dir(p) console.dir(Person)
The printed results are as follows:
- Instance objects have constructor attributes in their u proto_u attributes, which record their own construction methods.
- Person is both a construction method and an object, and the result we print directly from Person has an attribute prototype, which also has an attribute called constructor.It records that the construction method is itself.
- Combining the above examples, we can actually deduce that the constructor in both the prototype properties of the instance object and the prototype properties of the constructor point to the same construction method, and then we can further deduce that p is a Person type.
_u prototype_u is actually a prototype object, which is described in more detail below
As an example above, the following output will help you understand
console.log(p.constructor === Person) // true console.log(p.__proto__.constructor == Person) // true console.log(p.__proto__.constructor == Person.prototype.constructor) // true // Inferred from this, p === Person console.log(p instanceof Person) // true
There's a small problem. Look at the first line of console.log (p.constructor == Person) in the code above. We can't see the instance object p-constructor attribute through the code above. How can we use it without error undefined?
In fact, this is the chain of prototypes that involves js objects, (the following chapters will say). Generally speaking, js objects will take precedence over properties and methods in construction methods. If there are no properties and methods we use in the constructor, try to remove the properties and methods in the prototype objects in the corresponding construction methods for this object, and there will be no error.
2. Prototype of JS
2.1 Necessity of introducing prototypes
Why suddenly come back to see the prototype of js?
Since a lot of methods have been added to the vue's prototype in the source code, looking back at the prototype is certainly impossible to avoid.
Usually we use prototypes to save space.
Want to understand what space has been saved?Take a look at this space-saving example below.
// Problems with creating objects with constructors function Person(name) { this.name = name this.say = function () { console.log(this.name,": say hello") } } var p1 = new Person("tom") var p2 = new Person("jerry") p1.say() // tom : say hello p2.say() // jerry : say hello // todo returns false, meaning that the say methods of p1 and p2 are not the same, which is actually not a good thing console.log(p1.say == p2.say)
The P1 and P2 above are different objects created by a constructor. They all have a say function inside them. When we output p1.say == p2.say, we return false, indicating that there is a say method in each object. Assuming there are 1000 objects, isn't there 1000 say methods?It must be a waste of space.
So is there any way to have a say method for each new object?
Of course, the following:
// Shared Function, Derived Prototype function Say() { console.log(this.name, ": say hellp") } function Person(name) { this.name = name this.say = Say } var p1 = new Person("tom") var p2 = new Person("jerry") p1.say()// tom : say hellp p2.say()// jerry : say hellp // This saves space, but it's easy to go wrong console.log(p1.say == p2.say) // ture
Now we do what we need, but it's not elegant enough, and there's a problem with uniformity. js is a dynamic type of language, so let's assume we don't know there's already a Say function, and then put var Say = "hello" after the Say function, overrides will occur.
2.2 Understanding Prototype
Here's an example: Let's add a say method to the prototype object of the construction method.
Actually, it's not hard to understand. You know, js objects are created by construction methods. We put public methods and attributes in the prototype objects of construction methods, can they share these methods and attributes?
function Person(name) { this.name = name } // Add Method to Prototype // Why can we say that a prototype is an object?Think about an object in js that can add properties and methods through points, dynamic points? Person.prototype.say = function () { console.log(this.name,":say hello") } var p1 = new Person("tom") var p2 = new Person("jerry") p1.say()//tom :say hello p2.say()//jerry :say hello console.log(p1.say == p2.say) // true
By printing the instance object and constructor above with console.dir(), the following figure is obtained:
console.dir(p1) console.dir(p2) console.dir(Person)
As you can see from the figure above, you can draw the following conclusions:
- Standard attributes directly owned in the instance object, such as name, are attributes that appear directly in the construction method and are private to the js object.
- The instance object in the figure above has an attribute called: u proto_u, which is used by browsers, not programmers, so we call it a nonstandard attribute.In addition, Google browser supports this property, but in IE8 browser, we make an error when executing this console.log (p1. u proto_u), saying undefined
2.3 What is the relationship between prototypes, instance objects, and constructors?
-
Instance objects are created with the new constructor, so the constructor is a template for creating instance objects.
-
The constructor is that capitalized function, and in js we can console.log directly because it is actually an object.
-
The purpose of prototypes is to extract common methods and store them all in the prototype object of the constructor, while sharing data and saving memory.
-
The u proto_u of the instance object is both a nonstandard property and an object that points to the prototype property of the construction method.
-
The prototype property of a construction method is both a standard property and an object for which we add properties and methods by means of the construction method.prototype.property/method= XXX.
-
When we look through an object.property/method, we prefer to look through the object's construction method. If we can't find it, we try to look through the prototype again. That's why there is an object that clearly doesn't have a corresponding property or method added to it, but the object can be pointed out and used properly.Of course, undefined is a mistake if it doesn't exist in the prototype
2.4 About this object
- See the first example below
The following this is not hard to understand, it's the object we've just come out of
function Person(name) { // Consider who this is? this.name = name console.log(this) } var p = new Person("tom")
- See the second example below
We add a method say to the prototype object of the construction method, and the this object used in this say method refers to the same object that we new out.This is the caller of the method.
function Person(name) { // Consider who this is? this.name = name console.log("n10: ",this) } Person.prototype.say = function () { // Who does this refer to in todo? // First, the method is to add it to the prototype object. Does this refer to the prototype object? // As you can see from the console, this.name is not actually a prototype object, but the caller (instance object) of the say() method console.log("n16: ",this.name,": say hello") } var p1 = new Person("tom") var p2 = new Person("jerry") p1.say() p2.say()
- Look at the third example below:
Below, when you add a method to the prototype object of a construction method, not only this but also that appears.
The this object remains the object itself that we manually new out.
That also refers to the object that came out of our new est, so we need to go through it because inside the click event of a button, this refers to the button itself.
// Encapsulating constructors in an object-oriented manner function ChangeStyle(btnId, dvId, color) { this.btnObj = document.getElementById(btnId) this.dv = document.getElementById(dvId) this.color = color } // Add a method to the prototype of a construction method ChangeStyle.prototype.init = function () { // This this here represents an instance object that calls the init method var that = this this.btnObj.onclick = function () { // Why can't todo use this instead of that in a function in its prototype??? // todo or ask, who is this in the current function? that.dv.style.backgroundColor = that.color } }
2.5 Writing of Other Prototypes
- The most common way to write is to add attributes or methods based on the current prototype, as follows
function Person(name) { this.name = name } // In the previous example, we all wrote code like the following, which actually adds up the properties of the original prototype object // The original prototype object had a property called consturctor Person.prototype.say = function(){ //todo }
- You can also do the following
If you set the prototype this way, you are actually overwriting the original prototype object, so you need to re-add the constructor's direction as shown below.
I've also tried, of course, to get the right results when we use instanceof to determine whether an instance object is the corresponding constructor type, if we override the original prototype object without adding a guide to the contructor.
Person.prototype = { constructor:Person, // Manually modify the pointing of the constructor height:"20", weight:"20", say:function () { // todo } }
2.6 Inter-access between methods
- Membership methods in constructors are mutually accessible.
function Person(name) { this.name = name this.say = function () { console.log("say") // From this example, you can see that an object's method can be called directly from its method this.eat() } this.eat = function () { console.log("eat") } }
- The methods in the prototype are also mutually accessible.
function Person(name) { this.name = name } Person.prototype.say = function(){ console.log("say") // Methods in the prototype can also access each other this.eat() } Person.prototype.eat = function(){ console.log("eat") } var p1 = new Person("tom") p1.say()
2.7 Overriding methods in built-in object prototypes
This allows you to override the methods in the prototype.
Of course, you can extend the original encapsulation class by adding methods to the prototype.
// Doing this on an existing js wrapper class is also a modification of the source code String.prototype.myReverse = function () { for (var i = 0; i < this.length; i++) { console.log("Recursion occurs") } } var str = "123" str.myReverse()