上图的讲解
内存分为堆区和栈区,构造一个构造函数的实例以及构造函数的定义都是保存在堆区,并各自开辟一个空间。
上面的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();