js继承的四种方式超详细解读

对于不熟悉JS原型的小白,可以先去看下这篇JS原型和原型链
有利于下面对于JS继承方式的理解。

在ES6以前是没有类这些概念的,所以在继承方式上要从原型上开始。
一、原先链继承

 function Father() {
     this.name = 'yudong';
     this.age = 22
 };
Father.prototype.say = function() {
   console.log('我是帅哥');
 }
 //这里其实可以把父原型对象传给子原型对象,Son.prototype=Father.prototype,但缺点就是一旦改变子原型对象,父原型对象也会跟着改变,可以看下面的图,所以不采用这种。
Son.prototype = new Father();
//这里也要注意,Son原型对象被赋予父实例对象以后,Son原型对象的constructor属性会改变成Father,所以这里要重新赋值
Son.prototype.constructor = Son

function Son() {};
var son = new Son();
console.log(son.name);//yudong
console.log(son.age);//22
console.log(son.say);

js继承的四种方式超详细解读_第1张图片
Son.prototype=Father.prototype,但缺点就是一旦改变子原型对象,父原型对象也会跟着改变,不能传参。可以看下面的图,所以不采用这种。
js继承的四种方式超详细解读_第2张图片
Son.prototype = new Father();这种方式才是正确的
这种继承方式优点是:简单方便
缺点是:不能向父类传递参数

二、借用构造函数继承
使用这种方法前,我们必须call()的运用,看一下代码

function fn(){
	console.log(this.name);//yudong 在没有call调用之前this指向window,调用call指向O以后,this指向就变成指向O
}
var O={
	name:'yudong'
}
fn.call(O);
//call()方法有两个作用,1是调用函数的作用;2是改变this指向的作用
     function Father(name, age) {
            this.name = name;
            this.age = age;
            this.say = function() {
                console.log('我是帅哥');
            }
        };

        function Son(name, age) {
    //通过call()来改变this指向,这里指向来Son实例
            Father.call(this, name, age)
        };
        var son = new Son('yudong', 22);
        console.log(son.name); //yudong
        console.log(son.age); //22
        console.log(son.say());

这种继承方式同样存在缺点:每创建一个实例都会重新创建一遍方法,浪费内存

三、组合继承的方式
组合继承就是把原型链的方法继承和借用构造函数继承的属性继续结合起来,这样就可以避免上面浪费内存的缺点了,最大限度节省了内存,但还是会有缺点:会调用两次父类

	function Father(name, age) {
            this.name = name;
            this.age = age;
        };
        Father.prototype.say = function() {
            console.log('我是帅哥');

        }

        function Son(name, age) {
      //这里如果要传入多个参数,我们也可以用apply(this,arguments)来接受参数
            Father.call(this, name, age) //第一次调用
        };
        Son.prototype = new Father; //第二次调用
        var son = new Son('yudong', 22);
        console.log(son.name); //yudong
        console.log(son.age); //22
        console.log(son.say());

四、寄生组合继承
组合继承缺点是两次调用父类,那我们如何去改变这个缺点呢?
用寄生组合的方式可以完美解决这个问题

   		 function Father(name, age) {
            this.name = name;
            this.age = age;
        };
        Father.prototype.say = function() {
            console.log('我是帅哥');

        }

        function Son() {
            Father.apply(this, arguments)
        };
        //这里的内部原理先占个坑位,后面详细补上
        Son.prototype = Object.create(Father.prototype);
        Son.prototype.say = function() {
            console.log(111);

        }
        var son = new Son('yudong', 22, 133);
        var father = new Father();
        console.log(father.say);//Fathern.say

        console.log(son.name); //yudong
        console.log(son.age); //22
        console.log(son.say);Son.say

细节方面的东西先占个坑,比如寄生式继承原理等

你可能感兴趣的:(JS)