js的继承几种方式:
- es5的继承,原型链继承
(子的prototype= new 父,子的prototype.constructor = 子)
function Parent(name){
this.name = name
}
Parent.prototype.say = function(){
console.log(this.name)
}
function Child(age){
this.age = age
}
Child.prototype = new Parent('dhk')
Child.prototype.constructor = Child
var boy1 = new Child(39)
var boy2 = new Child(19)
缺点:1不能给父传值
boy1.arr.push(2)
boy2.arr // [1,2]
2引用类型的值是公共的。
- 构造函数继承(父在子的方法call(this,参数))
function Parent(name){
this.name = name
this.arr = [1]
this.say = function(){
console.log(this.name)
}
}
function Child(name,age){
Parent.call(this,name)
this.age = age
}
var boy1 = new Child('dhk',39)
var boy2 = new Child('duan',19)
缺点:1.不能继承父的prototype对象上的属性方法
2.重复实例父的this.方法
- 组合方法,把上面原型链方法和构造函数方法组合起来
(父.call(this,参数) 子.prototype = new 父 子.prototype.constructor = 子)
function Parent(name){
this.name = name
this.arr = [1]
this.say = function(){
console.log(this.name)
}
}
function Child(name,age){
Parent.call(this,name) // 第二次调用
this.age = age
}
Child.prototype = new Parent('dhk') //第一次调用
Child.prototype.constructor = Child
var boy1 = new Child('dhk',39)
var boy2 = new Child('kun',19)
解决了上面的缺点,但是产生新的缺点
缺点:重复实例了父对象的属性,因为实例了2次
- 优化组合继承1
function Parent(name){
this.name = name
this.arr = [1]
this.say = function(){
console.log(this.name)
}
}
function Child(name,age){
Parent.call(this,name)
this.age = age
}
Child.prototype = Parent.prototype
Child.prototype.constructor = Child // 因为没有实例对象,这时parent和child的原型都指向child了
var boy1 = new Child('dhk',39)
var boy2 = new Child('kun',19)
解决了上面的缺点,但是产生新的缺点
缺点:因为没有实例对象,这时parent和child的原型都指向child了
- 优化组合继承2,又称寄生组合继承
(Child.prototype = Object.create(Parent.prototype))
多继承:
other.call(child)
Object.assign(child.prototype, other.prototype)
function Parent(name){
this.name = name
this.arr = [1]
this.say = function(){
console.log(this.name)
}
}
function Child(name,age){
Parent.call(this,name)
this.age = age
}
Child.prototype = Object.create(Parent.prototype)
// 相当于Child.prototype.__proto__ = Parent.prototype
// 获取到原型,而且互相独立的
// 继承到Child.prototype的原型链上__proto__
Child.prototype.constructor = Child
var boy1 = new Child('dhk',39)
var boy2 = new Child('kun',19)
function MyClass() {
SuperClass.call(this);
OtherSuperClass.call(this);
}
// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;
MyClass.prototype.myMethod = function() {
// do a thing
};
- 对象冒充法继承
function Parent(username){
this.username = username;
this.hello = function(){
alert(this.username);
}
}
function Child(username,password){
//通过以下3行实现将Parent的属性和方法追加到Child中,从而实现继承
//第一步:this.method是作为一个临时的属性,并且指向Parent所指向的对象,
//第二步:执行this.method方法,即执行Parent所指向的对象函数
//第三步:销毁this.method属性,即此时Child就已经拥有了Parent的所有属性和方法
this.method = Parent;
this.method(username);//最关键的一行
delete this.method;
this.password = password;
this.world = function(){
alert(this.password);
}
}
var parent = new Parent("zhangsan");
var child = new Child("lisi","123456");
parent.hello();
child.hello();
child.world();
7.es6的最简单,关键字extends 、constructor、super()
// es6继承
class Animal {
//构造函数,里面写上对象的属性
constructor(props) {
this.name = props.name || 'Unknown';
}
//方法写在后面
eat() {//父类共有的方法
console.log(this.name + " will eat pests.");
}
}
//class继承
class Bird extends Animal {
//构造函数
constructor(props,myAttribute) {//props是继承过来的属性,myAttribute是自己的属性
//调用实现父类的构造函数
super(props)//相当于获得父类的this指向
this.type = props.type || "Unknown";//父类的属性,也可写在父类中
this.attr = myAttribute;//自己的私有属性
}
fly() {//自己私有的方法
console.log(this.name + " are friendly to people.");
}
myattr() {//自己私有的方法
console.log(this.type+'---'+this.attr);
}
}
//通过new实例化
var myBird = new Bird({
name: '小燕子',
type: 'Egg animal'//卵生动物
},'Bird class')
myBird.eat()
myBird.fly()
myBird.myattr()
构造函数、原型、对象的三角关系
自己实现new,分三步:
//自己定义的new方法
let newMethod = function (Parent, …rest) {
// 1.以构造器的prototype属性为原型,创建新对象;
let child = Object.create(Parent.prototype);
// 2.将this和调用参数传给构造器执行
Parent.apply(child, rest);
// 3.返回第一步的对象
return child;
};