prototype
js 构造函数有个 prototype,这样全部实例都可以访问公有池 prototype 里的方法和属性
constructor
每个对象都有个 constructor,指向构造这个对象的构造函数。这也是体现函数的严谨性。每个实例都会有这个指针指向构造他们的构造函数。也可以通过这个 实例.constructor.prototype 去改变属性和方法。
如果通过改变 prototype 的指向继承注意
o.prototype = {}; 之后一定要 o.prototype.constructor = o;
__proto__是系统自动生成的
每个实例都有一个__proto__指向父类的 prototype
继承的几种方式
1.构造函数绑定
function Cat(name,color){
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
2.prototype 模式 记住及时纠正 constructor
Cat.prototype = new Animal();
Cat.prototype = new Animal();
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
直接继承 prototype
因为一个类有私有属性和公用属性,通常继承只为了继承共有属性----> prototype 里面的
function Animal(){ }
Animal.prototype.species = "动物"
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
不过上面这种方式也有问题,子类对 prototype 的修改,直接通过索引改变了父类的 prototype 属性
利用空对象作为中介
由于直接继承 protototype 存在上述的缺点,所以就有这种方法,利用空对象作为中介。
let F = function() {}
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
可以封装成一个函数
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
// Child.uber = Parent.prototype;
}
拷贝继承
将父类的 prototype 遍历拷贝给子类 prototype
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}