一些继承方法

什么是继承?
一个原本没有某些方法和功能的对象,用过一些方法拿到另一个对象的属性和方法
构造函数的继承:

 function Fn(name){
        this.name = name;
        this.show = function(){
            alert(this.name);
        }
    }
    var obj1 = new Fn("AAA");
    var obj2 = new Fn("BBB");
    obj1.show()
    obj2.show()

改变this的指向 只能继承构造函数不能继承原型 可以向父类传参
call/apply继承:

 function Father(skill){
        this.skill = skill;
        this.show = function(){
            alert("我会"+this.skill);
        }
    }
    function Son(abc){
        //这里的this指向函数Son的实例化对象
        //将Father里面的this改变成指向Son的实例化对象,
        //当相遇将father里面所有的属性和方法都复制到了son身上
        //Father.call(this,abc);//继承结束,call适合固定参数的继承
        //Father.apply(this,arguments);//继承结束,apply适合不定参数的继承
    }
    var f = new Father("绝世木匠”);
    var s = new Son("一般木匠");
    f.show()
    s.show();
    //优点:创建子类实例时,可以向父类的构造器传参;
    //缺点:只能继承构造器中定义的属性和方法,不能继承原型上定义的属性和方法

call()方法接受的是若干个参数的列表,
apply()方法接受的是一个包含多个参数的数组。
这里要注意的是
两个参数都不是必填的,第一个参数在函数中使用时,根据场景不同指向也不一样,当不填时 默认指向的是window对象。
call/apply继承的区别
继承方面两者用法几乎一致,唯一的区别就是传参的时候,call是参数队列,apply是数组

function father(name, age) {
  this.name = name;
  this.age= age;
}
function child1(name, age) {
  father.call(this, name, age);
  this.category = 'child1';
}
function child2(name, age) {
  father.apply(this, [name, age]);
  this.category = 'child2';
}
var first= new child1('one', 11);
var second= new child2('two', 22);
console.log(first.category ,first.name,first.age) // child1,one,11
console.log(second.category ,second.name,second.age) //child2,two,22

原型对象继承:继承原型
缺点:只能继承原型,不能传参
优点:简单 方便 可以继承原型上的属性和方法
使原型prototype进行深拷贝

function Parent(n){
        this.name = n;
    }
    Parent.prototype.skill = function(){
        console.log(this.name + "是鉴定师");
    }

    function Child(n){}

    // 注意:对象的深浅拷贝
    // Child.prototype = Parent.prototype;
    for(var i in Parent.prototype){
        Child.prototype[i] = Parent.prototype[i];
    }

    // Child.prototype.skill = function(){
    //     console.log("采矿");
    // }

    var p = new Parent("大老王");
    console.log(p)
    p.skill();

    var c = new Child("小老王");
    console.log(c)
    c.skill();

原型链继承:
通过给子设置实例的方式 给子添加一层原型链的方式

function SuperType(){
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.Fun = function(){
 
};
function SubType(){
}
//继承了SuperType
SubType.prototype = new SuperType();
//优点:既能继承原型又能继承构造函数
//缺点:复杂  不方便传参

混合继承:
构造函数继承 + 原型继承
特点:
使用call或apply继承父类的构造器中的内容,使用原型继承,继承父类的原型

    function Father(skill,id){
        this.skill = skill;
        this.id = id;
    }
    Father.prototype.show = function(){
        alert("我是father,这是我的技能"+this.skill);
    }

    function Son(){
        Father.apply(this,arguments);
    }
    //如果不做Son的原型继承Father的原型,此时会报错:son.show is not a function
    for(var i in Father.prototype){
        Son.prototype[i] = Father.prototype[i];
    }
    //因为,如果不让Son的原型等于Father的原型,Son使用apply是继承不到原型上的方法
    Son.prototype.show = function(){
        alert("我是son,这是我的技能"+this.skill);
    }
    var f = new Father("专家级铁匠","father");
    var s = new Son("熟练级铁匠","son");
    f.show();
    s.show();
    //优点:方便传参 多继承
    //缺点:复杂

ES6 class继承:

class child extends Parent{
    constructor(n){
        super(n);
    }
}
//构造函数 + 原型链
//extends 关键字继承父级属性的方法
//优点:简单方便易操作 语法层面继承 属性和方法都能继承 参数很好处理 
//缺点:兼容性 IE5
//super关键字既可以当做函数使用,也可以当做对象使用
//super作为函数调用时 代表父类构造函数 ES6要求,子类的构造函数必须执行一个super
//super作为对象使用时 在普通方法中指向父类的原型对象,在静态方法中指向对象

检测两个对象之间是否存在继承关系
Fn.prototype.isPrototypeOf(f)查看Fn的prototype对象是否是f的原型
f instanceof FN 查看 f 对象是否是构造函数 Fn 的实例

发布了11 篇原创文章 · 获赞 12 · 访问量 466

猜你喜欢

转载自blog.csdn.net/weixin_45481771/article/details/101170514
今日推荐