关于构造函数的存储方式及调用方式

无标题.png

上图的讲解

  内存分为堆区和栈区,构造一个构造函数的实例以及构造函数的定义都是保存在堆区,并各自开辟一个空间。

  上面的Dog的构造函数现在开辟了一个的空间,并且栈区中B001这个空间,并在栈区中构建了两个空间,一个是B001,一个是B002,Boo1中拥有一个指向原型函数的指针,叫做prototype,B002中拥有一个指向构造函数的指针叫做constructor,原型函数中包含方法,且B001和B002互相指向,即为夫妻关系。

  var d1 = new Dog(),构造了一个叫做d1的Dog的实例,并且在堆区中开辟了一个空间,并且指向栈区中的B003,栈区中的B003中具有d1的所有变量以及Dog的构造函数(及d1的母亲)留给他的一个指向Dog的原型函数的一个指针(__proto__),因此d1可以使用Dog原型函数中的方法。

  下方的Person的构造函数,基本原理和上方一模一样,只不过Perosn的原型函数改成了Dog的原型函数,下方代码中有具体的介绍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function Dog(name,age){
this.name = name;
this.age = age;
} //构造Dog的构建方程

Dog.prototype= {
constructor:Dog,
sayName:function(){
console.log("My name is",this.name);
},
sayAge:function(){
console.log("My age is",this.age);
},
sayGender:function(){
console.log("My gender is",this.gender);
}
} //在Dog的原形函数(就是prototype,并且实例的方法调用都是来自prototype,所以在数组的函数重构时,都是在Array.prototype.xxx中加入)中加入一些方法

function Person(name,age,gender){
Dog.call(this,name,age);
this.gender = gender;
} //构造Peroson的构造函数

Person.prototype = new Dog(); //将Person的原型函数(prototype)改成Dog的prototype,更换方式为将person的prototype变为Dog的实例
Person.prototype.constructor = Person; //将Person的创造函数变为他本身,如果没有这一步那么之后的console.log(person的实例),输出的实例将是Dog的

Person.prototype.sayHello = function(){
console.log("Hello world");
} //在Person的prototype(即Dog的prototype)中加入SayHello这个方法

var d1 = new Dog("jiangjun",21); //创建一个Dog的实例
var p1 = new Person("xiaomiao",21,"male"); //创建一个Person的实例

console.log(d1); //输入Dog实例
console.log(p1); //输出Person的实例

d1.sayName(); //d1调用Dog的prototype中SayHello这个方法
d1.sayAge(); //d1调用Dog的prototype中sayAge这个方法

//下面相类似
p1.sayName();
p1.sayAge();
p1.sayGender();
p1.sayHello();