JS继承方式

3 篇文章 0 订阅
3 篇文章 0 订阅

new做的几件事:

	1. 在构造函数中创建一个空对象
	2. 函数的this指向空对象,并且将这个对象的隐式原型			              (proto)指向构造函数的原型(prototype)
	3. 逐行执行代码
	4. 隐式返回这个对象

new 实际上是把构造函数原型(prototype)上的属性放在了原型链(proto)上,那么当实例化对象取值时就会在原型链上取,而实例化对象上的prototype已经不见了

继承:通过构造函数创建的对象,可以直接继承该构造函数原型上的属性和方法。
构造函数之间实现继承:A构造函数中有的属性和方法,B构造函数也可以用 (B继承自A、A是B的父类)

1.传统继承方式(类式继承)(原型链继承)

function A(){}
			
        A.prototype.name = "123";//在A的原型上添加属性

        function B(){}
        B.prototype.age = '18';//在B的原型上添加属性
				// 使B的原型指向A的原型
        // 让B创建对象能够使用A原型上的属性和方法
				//以下三种方法相同
        B.prototype = A.prototype;
				//B.prototype = new A() //类式继承
				// var b = new B();b.__proto__ = A.prototype;
       

        var obj = new B();

        console.log(obj.name);  // 123
        console.log(obj.age); // undefined

        // 将自身的该继承的属性和方法都丢掉了  

原理:使B的原型指向A的原型;
优点:简单的一行代码,B创建的对象继承了A的原型上的所有属性和方法
缺点:
■ 子类只能继承一个父类(因为继承方式是直接修改子类的prototype,如果再次修改,会将其覆盖)
■ B原型上的方法和属性都被丢弃了,B创建的对象不能继承自身
■ 子类通过prototype继承父类,只能父类单向传递属性给子类,无法向父类传递参数。为什么要向父类传递参数?如果父类中的某属性对参数有依赖关系,此时子类继承父类就需要在 new SuperClass() 时传参

2.借用构造函数继承(构造函数继承)

function A1(name) {
            this.name = "111"
        }

        function A2(arr) {
            this.arr = [1, 2, 3]
        }

        function A3(f) {
            this.f = f
        }

        function A4() {
            this.qq = 1529588254;
        }

        function B(name, arr, f) {
            A1.call(this, name);
            A2.call(this, arr);
            A3.call(this, f);
            A4.call(this)
        }

        var b = new B(111, [2, 6, 9], function() {
            console.log(666);
        })
        console.log(b);
		b的打印结果如下

在这里插入图片描述

原理:调用其他构造函数里的方法,对自身的数据进行构造
优点:可以继承多个父类的属性,可以动态传递需要的参数来构建数据
缺点:无法继承原型中的属性和方法,无法继承在构造函数外添加的新属性

3.组合继承

		// 借用构造函数

        function User(name, age, phone, ID) {
            this.name = name;
            this.age = age;
            this.phone = phone;
            this.id = ID;
        }
        User.sayHello = function() {
                console.log(`我叫${this.name},我的身份证${this.id}`);
            }
            // var user = new User('闫振',38,1111,2222);


        // 实现VIP与User之间的继承关系    关键步骤1
				// 使VIP的原型 指向一个空对象,空对象的隐式原型为User的原型
				// 即让VIP的原型的隐式原型指向User的原型
				// 原型式继承
        VIP.prototype = Object.create(User.prototype);

        function VIP(name, age, phone, ID, money) {
            // 借用普通用户的构造函数来给自身对象添加属性
            User.apply(this, arguments);   关键步骤2
            // User(name,age,phone,ID); // this  =》 window
            // User.call(this,name,age,phone,ID);// this -> {}
            this.money = money;
        }
        VIP.prototype.update = function() {
            this.money -= 1000;
            console.log('又花了1000大洋');
        }
        var vipUser = new VIP('闫振', 38, 1111, 2222, 50000000);

        // VIP 继承 User
        vipUser.sayHello(); // vipUser.__proto__ => Vip.prototype => Object.prototype

原理:调用其他构造函数里的方法,对只身的数据进行构造的同时,通过一个中转对象把自身链接到目标(父级)函数的原型链上。则可以调用父级原型链上的属性和方法。
优点:能够使用父级构造函数原型链上的属性和方法,也能通过父级构建自身的属性
缺点:

4.圣杯模式(组合寄生式继承)

// 将一个构造函数的原型继承另一个构造函数的原型

        // 圣杯模式
        // 将继承这件事做了封装  封装成一个函数
        A.prototype.sayHello = function(){
            console.log(this);
        }
        function A() {}
        function B() {}


				//原型式继承
        // function inherit(son,father){
        //     // 实现继承
        //     function F(){};  
        //     F.prototype = father.prototype;
        //     son.prototype = new F();

        //     // 将son原本的构造函数给他复原
        //     son.prototype.constructor = son;
        //     // 记录son原本继承自谁
        //     son.prototype.uber = father.prototype;
        // }

        // inherit(B,A);

        // console.log(B.prototype.constructor); // A

        // var b = new B();
        // b.sayHello();



				//封装后放入Function的原型链,方便调用
        Function.prototype.inherit = function(Father){
            // this -》 调用的对象

            function F(){}
            F.prototype = Father.prototype;
            this.prototype = new F();
            // 做一些记录,记录原本的属性应该是什么
            this.prototype.constructor = this;
            this.prototype.uber = Father.prototype;
        }

        B.inherit(A);

        var b = new B();
        b.sayHello();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值