In js, variables include 5 basic types and a complex data type Object. Of course, common functions and arrays are all objects. For basic and complex types, there are two different storage methods-
Basic Principles
In js, variables include 5 basic types and a complex data type Object. Of course, common functions and arrays are all objects. For basic and complex types, there are two different storage methods: Stack storage and Heap Storage. The reason for implementing the two storage methods is simple: the memory size is fixed once the basic type is initialized, And the access variable is the actual data in the memory of the access variable, which is called value-based access. The object type may increase its size at any time, and the memory size is not fixed. For example, the dynamic addition of object attributes and the dynamic addition of array size will increase the variable size and cannot be maintained in the stack. Therefore, js puts the object-type variables in the heap, allowing the interpreter to allocate memory for it as needed, and access it through the object reference pointer, because the memory address size of the object in the heap is fixed, the memory address can be stored in the reference of stack memory. This method is called access by reference. Well, it is very important to understand this point and avoid many problems in future programming. Let's take a look at the following code:
Var a = 'I am a string. '; // the actual values are saved in the variables a, B, and c, because they are basic variables var B = 1010; var c = false; var d = a; // d stores copies with the same value as a. They do not affect each other. "a = 'I am different from d'; alert (d ); // output 'I am a string'
The above code is easy to understand, that is, copying the variables accessed by value "Yours is yours, mine is mine, and we all have copies, which do not affect each other ." Access by reference is slightly different:
Var e = {name: 'I am an object', setName: function (name) {this. name = name ;}}; var f = e; // value assignment operation. In fact, the result is e, and f is the reference pointer to that object. setName ('I am different from e, I am object f. '); alert (e. name); // The f operation, and the value of e is also changed!
To put it bluntly, we copied the pointer of that object. The two pointers point to the same object and there is no copy. The original object still has only one! Okay. The above is the biggest fundamental difference between the basic type and the reference type! I use a picture to represent the following:
* Stack and heap Replication
Problems caused by reference types
1. Questions about using a prototype model to create objects
As we all know, in JavaScript OO (Object Oriented), the biggest benefit of creating an Object in prototype mode is to allow the Object instance to share the attributes and methods contained in the prototype. This avoids the constructor pattern defect, that is, each object will have a copy of each method, and each method will be re-created on each instance, so that method reuse is meaningless.
Well, the prototype mode is used to share the method for all instances. But when the prototype has the property of the reference type value, the problem arises:
Var Person = function () {}; Person. prototype = {constructor: Person, name: 'hanzongze', Hober: ['bucketable', 'running', 'running'], // note, A reference type property sayName: function () {alert (this. name) ;}}; var person1 = new Person (); var person2 = new Person (); person1.hober. push ('music'); alert (person2.hober); // The output is 'bucketable', 'playing in', 'running', 'music' alert (person1.hober = person2.hober ); // true
Because the holobby attribute is a value of the reference type, the holobby attribute of the Instance created by the Person constructor points to this referenced object, and the attributes of instance objects are mutually disturbed. This is not the expected result. To avoid such problems, the solution is to combine the constructor model and the prototype model:
Var Person = function () {this. name = 'hanzongze'; this. holobby = ['bucketable', 'running', 'running']; // use the constructor mode for the value of the reference type}; Person. prototype = {constructor: Person, sayName: function () {alert (this. name) ;}}; var person1 = new Person (); var person2 = new Person (); person1.hober. push ('music'); alert (person2.hober); // output 'bucketable', 'playing in', 'running ', the modification to person1 does not affect person2alert (person1.hober = person2.hober); // false
2. Problems in prototype inheritance
This problem is essentially the same as the previous one, but only occurs in the context of prototype inheritance. Let's look at a prototype chain inheritance question:
Var Person = function () {this. name = 'hanzongze'; this. holobby = ['bucketable', 'running', 'running'];}; Person. prototype = {constructor: Person, sayName: function () {alert (this. name) ;}}; // subtype Studentfunction Student () {} Student. prototype = new Person (); // Student inherits Personvar student1 = new Student (); var student2 = new Student (); student1.hoby. push ('music'); // modify the reference attribute of student1 In the subclass instance var student3 = new Student (); alert (student2.hober); // output 'bucketable ', 'running', 'running', 'music' alert (student3.hober); // output 'bucketable', 'running', 'music'
In this code, we can see that the sub-class Student inherits from the parent class Person. However, because prototype inheritance is used, that is, the instance of the parent class acts as the prototype of the subclass, the reference type attribute in the instance is inherited from the prototype of the subclass. Then the instance of the subclass shares the reference property and affects each other.
The solution is to use the borrow constructor Scheme (but it is not an ideal solution. The ideal solution is to combine the prototype chain and borrow constructor. It involves many inheritance modes. Here is a brief description, and I will write a detailed article later ):
Var Person = function () {this. name = 'hanzongze'; this. holobby = ['bucketable', 'running', 'running'];}; Person. prototype = {constructor: Person, sayName: function () {alert (this. name) ;}}; function Student () {// borrow the constructor and inherit the PersonPerson. call (this);} var student1 = new Student (); var student2 = new Student (); student1.hoby. push ('music'); alert (student2.hober); // output 'bucketable', 'playing in', 'running', 'music'