我们将构造函数称之为类,一个类可以构建多个对象
对于储存空间:基本属性,放在我们自身,公用的方法,可以放在prototype中共用
继承的方式:
1.原型链的方式
缺点:非顶层的属性会丢失(比如下面Father中的gender)
function Grandpa(name, age) { this.name = name; this.age = age; } Grandpa.prototype.sayName = function() { console.log(this.name); }; function Father(name, age, gender) { this.constructor(name, age); this.gender = gender; } Father.prototype = new Grandpa(); Father.prototype.sayha = function(){ console.log(888); }; function Child(name, age, gender) { this.constructor(name, age, gender);//通过这个来获取上一层的参数, } Child.prototype = new Father(); //prototype本来是指向Child本身,现在赋值为Father var c1 = new Child("lisi", 78, "mail"); console.log(c1); c1.sayName(); c1.sayha();
2 对象混合:
原理:让父类的构造函数称为子类的方法,然后调用该子类的方法,通过this关键字给所有属性和方法进行赋值
3 call()方法.apple()方式
原理:手动改变this的指向,使它指向传入函数的具体对象
4.混合
基本属性通过对象冒充的方式,方法还是放在顶层的prototype身上,通过原型链的的方式
function Grandpa(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } Grandpa.prototype.sayName = function() { console.log(this.name); }; function Father(name, age, gender) { this.obj1 = Grandpa; this.obj1(name, age, gender); delete obj1; } Father.prototype = new Grandpa() function Child(name, age, gender) { // this.obj = Father;//改变Father中this的指向 // this.obj(name,age); //获取Father的属性 // delete obj; //只需要Father的属性,不需要这个函数 // Father.call(this,name,age); Father.apply(this, [name, age, gender]); //call、apple手动改变this的指向,两者在本质上是一样的 } Child.prototype = new Father(); var c1 = new Child("zhangsan", 39, "mail"); console.log(c1); c1.sayName();
总结:
js并不是面向面向对象的语言,而是通过原型的方式来实现继承的效果。
继承有几种情况,
1,原型链继承:但这个会有一个缺点;层级多了之后非顶层的属性会丢失。
2,对象冒充的方式:本质上就改变父级this的指向,缺点是只能获取属性,方法还得用原型链的方式
3, call()方法apple()方法,这两个方法本质上是一样的,只有参数有点不一样,缺点也跟对象冒充一样。
混合:用对象冒充或call或apple来获取基本属性,方法写在顶层的prototype中共用,通过原型链的方式来传递。