面向对象、prototype、原型链、继承

本文详细介绍了面向对象编程的核心概念,包括继承、封装和多态。通过实例展示了如何在JavaScript中实现这些特性,如使用构造函数、原型和`new`关键字。同时,解释了原型链的工作原理以及如何利用原型实现属性和方法的共享。此外,还探讨了ES6中的类和继承,展示了与ES5的不同之处。
摘要由CSDN通过智能技术生成

面向对象认识

面向对象(OOP,即 Object Oriented),是相对于面向过程来讲的,简单说就是把数据和方法组合封装起来成为一个整体,提高软件的重用性、灵活性和扩展性。

面向对象特点:

  • 继承,即子类自动分享父类数据结构和方法

  • 封装,捆绑数据和方法,但是对于某些私有的数据和方法,不可被外界访问,就封装起来区分访问权限

  • 多态,即对于同一函数,因对象不同,结果不同

            let ww = {
                name : "魏无羡",
                age : 18,
                sex : "男",
                say : function () {
                    console.log(`我的名字是${ww.name},已经${ww.age}岁了,我是${ww.sex}生`);
                }
            }
            ww.say()
    

    有需要要写多个类似的对象时,可用下面这种方法来写

            function Person(name,age,sex){
                let obj = {}
                obj.name = name
                obj.age = age
                obj.sex = sex
                obj.say = function (){
                    console.log(`我的名字是${obj.name},已经${obj.age}岁了,我是${obj.sex}生`);
                }
                return obj
            }
            let ww = Person("魏无羡",18,"男")		// 这种叫做实例,是对象Person的实例
            ww.say()
            let ll = Person("蓝忘机",20,"男")
            ll.say()
    
    new 关键词

    用的比较多的:

    new Date()

    new Object()

    new Array()

    new RegExp()

    new XMLHTTPRequest()

    new Promise()

    new Image()

    函数执行前加new的影响
    • 加new后,函数内部会自动创建一个全新的对象,所以函数内部的this指向就会转变,指向这个对象。
    • 不加new时,函数默认返回undefined;加new后,函数默认返回自动创建的对象。

一、prototype

当创建的对象较多时,会有可共用的属性,此时就可用prototype。

比如我们用Array来创建一个实例时,不用我们定义,它本身就具有Pop、push、join等方法,且这些方法存在于构造函数的_proto_中。这样我们就可以理解为前辈将可能使用到的方法都写到函数的proto中,当我们创建实例,想要去使用某一方法时,其实就是使用了共有属性。例: (此处的let a = [] 是 let a = new Array() 的简写)
在这里插入图片描述

        function Students(name, id) {
            // 每个实例私有属性
            this.name = name
            this.id = id
        }
		// 共有属性
        Students.prototype.campus = "云深不知处"
        Students.prototype.say = function (){
            console.log(`我的名字是${this.name},是${this.campus}的学生,学号是${this.id}`);
        }

        let ww = new Students("魏无羡",1213)
        ww.say()
        let ll = new Students("蓝忘机",1314)
        ll.say()


//我的名字是魏无羡,是云深不知处的学生,学号是1213
//我的名字是蓝忘机,是云深不知处的学生,学号是1314

二、原型链

如上面那个代码,函数Students的prototype指向了一个对象,这个对象就是在调用构造函数时创建的实例的原型,也就是ww和ll的原型。
在这里插入图片描述

       function fn(){
            this.x = 10
        }
        fn.prototype.x = 20
        let ss = new fn()
        console.log(ss.x);  // 10  ,  其优先访问私有属性
        console.log(ss.__proto__);    // {x:20, constructor: f}
        console.log(fn.prototype);  // {x:20, constructor: f}
        console.log(ss.__proto__ === fn.prototype);     // true
console.log(fn.prototype);  // 打印如下,可以看出所有原型链的顶端都是object

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

三、继承(ES5写法)

注意:默认构造函数的首字母大写

        function Person(name, age){
            this.name = name
            this.age = age
        }
        Person.prototype.say = function (){
            console.log(this.name + ":" + this.age);
        }

		// 子可继承父的东西,父不能使用子的东西,且子可新增
        function Students(name, age, id){
            // 私有属性继承
            Person.call(this,name,age)
            // 私有属性新增
            this.id = id
        }
        let aa = new Person("ajs",15)
        console.log(aa.name);       // ajs
        console.log(aa.age);        // 15
        console.log(aa.id);         // undefined
        aa.say()                    // ajs:15

        let ss = new Students("魏无羡",18, "0012")
        console.log(ss.name);       // 魏无羡
        console.log(ss.age);        // 18
        console.log(ss.id);         // 0012

		// 原型的继承。还可用方法二、三
        Students.prototype = Person.prototype
		ss.say()					// 魏无羡:18
        // 原型的继承
        // 方法一:两方为引用关系,一方改变,另一方也会变。Students新增属性时会改变原型Person
        Students.prototype = Person.prototype

        // 方法二: 创建实例的方法,也为引用关系,但当Students改变时,原型Person不会改变。且Students下的属性有参数,但其prototype中的属性无参数
        Students.prototype = new Person()

        // 方法三: 
        function Fn(){}
        Fn.prototype = Person.prototype
        Students.prototype = new Fn()       // 此时Students的原型为Fn(),
        //修复   每个函数默认 Person.prototype.constructor = Person
        Students.prototype.constructor = Students

        // 原型的新增
        Students.prototype.campus = "内容"

四、ES6构造函数

        class Person{
            // 私有属性
            constructor(name, age){
                this.name = name
                this.age = age
            }

            // 公有属性,只能用函数形式
            say (){
                console.log(this.name + ":" + this.age);
            }
        }
        // 继承
        class Students extends Person{
            constructor(name, age, id){
                super(name, age)        // 执行后,才能继承Person的私有属性
                this.id = id
            }
            campus(){               // Students的共有属性
                return "云深"
            }
        }

        let ww = new Students("魏无羡",18,"0012")
        console.log(ww.name);           // 魏无羡
        console.log(ww.age);            // 18
        console.log(ww.id);             // 0012
        ww.say()                        // 魏无羡:18
        console.log(ww.campus());       // 云深

        let ll = new Person("蓝忘机",20,"1314")
        console.log(ll.name);           // 蓝忘机
        console.log(ll.age);            // 20
        console.log(ll.id);             // 1314
        ll.say()                        // 蓝忘机:20
        // console.log(ll.campus());       // 报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值