七十二——八十八

七十二、JavaScript——面向对象简介

 面向对象编程(OOP)

                1. 程序是干嘛的

                    - 程序是现实世界的抽象(照片就是对人的抽象)

                2. 对象是干嘛的?

                    - 一个事物抽象到程序后就变成了对象

                    - 在程序的试接中,一切皆对象

               

                - 一个事物通常由两个部分组成,数据和功能

                - 一个对象由两部分组成:属性和方法

                - 静态的就是属性,动态就是方法

                - 事物的数据到了对象中,体现为属性

                - 事物的功能到了对象中,体现为方法

    
    <script>
        const five = {
            name: "张三",

            sleep(){
                console.log(this.name+"在睡觉")
            }
        }

    </script>

七十三、JavaScript——类的简介

使用Object创建对象的问题

                1. 无法区分不同类型的对象

                2. 不方便批量创建对象

            在JS中可以通过类(class)来解决这个问题

                1. 类是对象模板,可以将对象中的属性和方法直接定义在类中

                    定义后,就可以直接通过类来创建对象

                

                2. 通过同一个类创建的对象,我们称之为同类对象,

                    可以使用onstanceof来检查一个对象是否由某个类创建的
 

            语法

                class 类名 { }   类名要使用大驼峰命名   class Person {}

                const 类名 = class  { }

  // Person类专门用来创建人的对象
        class Person {

        }

        const p1 = new Person()

        //打印p1
        console.log(p1)
        // 利用instanceof检查p1是否由Person创建
        console.log(p1 instanceof Person)

 七十四、JavaScript——属性

实例属性

        new出来的p1和p2都是实例

        访问实例属性  实例.属性名(p1.name)

类属性

         使用static声明的属性,是静态属性(类属性)

        类中加了static的属性就是类属性

        访问类属性   类.属性名(Person.test)

 <script>

        /*

            类是创建对象的模板,要创建第一件事就是定义类
        */

        class Person {
        /*


            类的代码块,默认就是严格模式
                类的代码是用来设计对象的属性的,不是什么代码都能写

        */
            name   // Person的实例属性name,new出来的p1和p2都是实例
            age    // Person的实例属性age

            static test = "test是静态属性"  // 使用static声明的属性,是静态属性(类属性),只能通过 类.属性去访问 例 Person.test
        }

        const p1 = new Person()

        console.log(p1)
        
        
        const p2 = new Person()

        console.log(p2)

    </script>

七十五、JavaScript——方法

实例方法

        new出来的p1是实例

        访问实例方法  实例.属性方法名(p1.sayHello())

类属性

         使用static声明的方法,是静态方法(类方法)

        类中加了static的方法就是类方法

        静态方法中,this指向的是当前类

        访问类属性   类.方法名(Person.test())

        

  <script>


        class Person {


            name = "张三";

            // 添加方法的一种方式
            sayHello = function() {

            }

            // 添加方法的另一种方式(实例方法)
            sayHello() {

                // 这里的this指的是实例对象,这里的实例对象是p1,
                console.log("大家好,我是" + this.name)
                
            }

            // 静态方法,使用static声明的方法,只能通过 类.方法 调用
            // 静态方法中,this指向的是当前类
            static test() {

                console.log("我是静态方法", this)
            }
        }

        const p1 =new Person()

        p1.sayHello()

    </script>

 七十六、JavaScript——构造函数

    <script>


        // class Person {
        //     // 当我们在类中直接指定实例属性的值时,意味着我们创建的所有对象的属性都是这个值
        //     name = "张三"
        //     age  = 12
        //     gender = "男"

        //     sayHello() {

        //         console.log(this.name)
        //     }
        // }

        // // 创建一个Person实例
        // const p1 = new Person()


        

        class Person{


            name
            age
            gender
            // 在类中可以添加一个特殊的方法constructor
            // 该方法我们称之为构造函数 (构造方法)
            // 构造函数会在我们调用类创建对象时执行,new的时候执行
            constructor(name, age, gender){
                // 在构造函数中,为实例属性进行赋值
                // 在构造函数中,this表示当前所创建的对象
                this.name = name
                this.age = age
                this.gender = gender
                
            }

           
        }

        // 直接在创建对象时就进行赋值,因为有构造函数
        const p1 = new Person("张三", 18, "男")
        const p2 = new Person("李四", 11, "女")


    </script>

 七十七、JavaScript——封装

面向对象的特点

                封装、继承和多态

            1.封装

                - 对象就是一个用来存储不同属性的容器

                - 对象不仅赋值属性,还要 赋值数据安全

                - 直接添加到对象中的属性,并不安全,因为他们可以被任意的修改

                - 如何确保数据的安全

                    1. 私有化数据

                        - 将需要的保护的数据设置为私有,只能在内部使用

                        - 私有化数据需要先声明再使用

                        - 实例使用#开头就变成了私有属性,私有属性只能在类内部访问

                    2. 提供setter和getter方法来开放对数据的操作

                        - 属性设置私有, 通过getter和setter方法操作属性带来的好处

                            1. 可以控制属性的读写权限

                            2. 可以在方法中对属性的值进行验证

                    - 封装主要用来保证数据的安全

                    - 实现封装的方式

                        1. 属性私有化 : 属性名前加#

                        2. 通过gettersetter方法来操作属性

                            get 属性名() {

                                return this.#属性名

                            }

                            set 属性名(参数){

                                this.#属性 = 参数

                            }

 使用gettert和setter推荐使用第二种写法:

 class Person{


           

            // 封装属性前线声明
            #name 
            #age
            #gender
            


            constructor(name, age, gender){

                this.#name = name 
                this.#age = age
                this.#gender = gender
            }

            // 第一种写法:获取私有属性的方法
           getName() {

            return this.#name
           }

           // 第一种写法:修改私有属性
           setName(name) { 

            this.#name = name
           }


           // 另一种写法(推荐使用)
           get age() {
            return this.#age
           }

           // 另一种写法(推荐使用)
           set age(age){
            this.#age = age
           }

        }

        const p1 = new Person("张三", 19, "男")

        //  第一种写法的修改
        p1.setName("李四")


        // 第一种写法的获取
        console.log(p1.getName())

        //  第二种写法的修改(推荐使用)
        p1.age = 11

        // 第二种写法的获取(不需要加括号)(推荐使用)
        console.log(p1.age)

    </script>

七十八、JavaScript——多态

<script>

        class Person {
            constructor(name) {
                this.name = name
            }
        }

        class Dog{
            constructor(name){
                this.name = name
            }
        }

        const dog1 = new Dog("旺财")

        const p1 = new Person("小李")

        /*
            定义一个函数,这个函数将接收一个对象作为参数,它可以输出hello并打印对象的name属性


            多态
                - 在JS种不会检查参数的类型,所以这就意味着任何数据都可以作为参数传递
                - 要带调用某个函数,无需指定的类型,只要对象满足某些条件即可
                - 多态为我们提供了灵活性


        */
        function sayHello(obj){

            console.log("Hello" + obj.name)
        }
        
        // dog1对象和p1对象的类中都有name的属性,所以可以成功调用
        sayHello(dog1)

    </script>

七十九、JavaScript——继承

继承

                - 可以通过extends关键字来完成继承

                - 当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类中(简单理解)

                - 继承发生时,被继承的类i称为 父类(超类),继承的类称为 子类

<script>

        /*
            继承
                - 可以通过extends关键字来完成继承
                - 当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类中(简单理解)
                - 继承发生时,被继承的类i称为 父类(超类),继承的类称为 子类
        */
        class Animal{
            constructor(name){
                this.name = name
            }

            sayHello() {
                console.log("动物在叫")
            }
        }




        class Dog extends Animal{
            
        }


        class Cat extends Animal{
           
        }

        const dog = new Dog("旺财")

        const cat = new Cat("小喵")

        dog.sayHello()
        cat.sayHello()

        console.log(dog)


    </script>

八十、JavaScript——继承

<script>


        /*
            继承
                - 通过继承可以在不修改一个类的情况下对其进行拓展
                - OCP原则
                    - 程序应该对修改关闭,对扩展开放
        */


          class Animal{
            constructor(name){
                this.name = name
            }

            sayHello() {
                console.log("动物在叫")
            }
        }




        class Dog extends Animal{


            // 在子类中,可以通过创建同名方法来重写父类的方法
            sayHello(){

                console.log("汪汪汪")
            }
            
        }


        class Cat extends Animal{
           
            // 重写构造函数
            constructor(name, age){
                // 重写构造函数时,构造函数的第一行代码必须为super()
                super(name)  // 调用父类的构造函数
                this.age = age
            }


            // 在方法中调用父类的方法  super.父类方法名
            sayHello() {

                // 调用父类的sayHello
                super.sayHello() // 在方法中可以使用 super来调用父类的方法
                
                console.log("喵喵喵")
            }
        }

        const dog = new Dog("旺财")

        const cat = new Cat("小喵", 67)

        dog.sayHello()
        cat.sayHello()

        console.log(dog)

        console.log(cat)

    </script>

八十一、JavaScript——对象的结构

对象中存储属性的区域实际有两个

             1. 对象自身

                - 直接通过对象添加的属性,位于对象自身中

                - 在类中通过 x = y 的形式添加的属性,位于对象自身中

             2. 神秘位置:(prototype)

                - 对象中还有一些内容,会存储到其他对象里(原型对象

                - 在对象中会有一个属性用来存储原型对象,这个属性叫__proto__

                - 原型对象也负责为对象存储属性

                    当我们访问对象中的属性时,会优先访问对象自身的属性

                    对象自身不包含该属性时,才会去原型对象中寻找

                - 会添加到原型对象的情况

                    1. 在类中通过xxx( ){ }方式添加的方法,位于原型中

                    2. 主动向原型中添加属性和方法,

 <script>
        /*

             对象中存储属性的区域实际有两个
             1. 对象自身
                - 直接通过对象添加的属性,位于对象自身中
                - 在类中通过 x = y 的形式添加的属性,位于对象自身中

             2. 神秘位置:(prototype)
                - 对象中还有一些内容,会存储到其他对象里(原型对象)
                - 在对象中会有一个属性用来存储原型对象,这个属性叫_proto_
                - 原型对象也负责为对象存储属性
                    当我们访问对象中的属性时,会优先访问对象自身的属性
                    对象自身不包含该属性时,才会去原型对象中寻找
                - 会添加到原型对象的情况
                    1. 在类中通过xxx( ){ }方式添加的方法,位于原型中
                    2. 主动向原型中添加属性和方法,

        
        */


        class Person{
            name = "孙悟空"


            // 原型对象的sayHello
            sayHello(){

                console.log("Hello,我是"+ this.name)
            }
        }

        const p = new Person()

        // p对象中的sayHello
        p.sayHello = "hello"


        // 线访问对象自身,再访问原型对象,最后访问父类
        console.log(p.sayHello)

    </script>

八十二、JavaScript——原型

访问一个对象的原型对象

                1. 对象.__proto__

                2. JS内置的访问原型对象: Object.getPrototypeOf(对象名)

            原型对象中的数据

                1. 对象中的数据(属性,方法等)

                2. constructor (对象的构造函数)

            注意

                原型对象也有原型,这样就构成了一条原型链,根据对象的复杂程度不同,原型链的长度也不同

                    p对象的原型链:p对象 -- 原型 -- 原型 -- null

                原型链:

                    - 读取对象属性时,会优先对象自身属性

                        如果对象中有,则使用,没有就去对象的原型中找

                        如果原型中有,则使用,没有则去原型的原型中寻找

                        直到找到Object对象的原型,Object的原型没有原型(为null)

                            如果依然没有找到,找到obj.__proto__还没有,则返回undefined

                    - 作用域链,是找变量链

                    - 原型链,是用来找属性的,找不到会返回undefined

  <script>

        
        class Person{
            name = "张三"
            age = 18

            sayHello(){
                console.log("我是" + this.name)
            }
        }

        /*
            访问一个对象的原型对象
                1. 对象.__proto__
                2. JS内置的访问原型对象: Object.getPrototypeOf(对象名)

            原型对象中的数据
                1. 对象中的数据(属性,方法等)
                2. constructor (对象的构造函数)

            注意:
                原型对象也有原型,这样就构成了一条原型链,根据对象的复杂程度不同,原型链的长度也不同
                    p对象的原型链:p对象 -- 原型 -- 原型 -- null

                原型链:
                    - 读取对象属性时,会优先对象自身属性
                        如果对象中有,则使用,没有就去对象的原型中找
                        如果原型中有,则使用,没有则去原型的原型中寻找
                        直到找到Object对象的原型,Object的原型没有原型(为null)
                            如果依然没有找到,找到obj.__proto__还没有,则返回undefined

                    - 作用域链,时找变量链
                    - 原型链,是用来找属性的,找不到会返回undefined




       */

       const p = new Person()

       // 访问原型对象
        console.log(p.__proto__)
    </script>

八十三、JavaScript——原型的作用

所有的同类型对象他们的原型对象都是同一个

                也就意味着同类型的原型链是一样的

            原型的作用:

                原型就相当于是一个公共的区域,可以被所有该类实例访问

                这样我们只需要创建一个属性,都可以被所有实例访问

            JS中继承就是通过原型来实现的

                当继承时,子类的原型就是父类的实例

            在对象中,有些值是对象独有的,像属性(name,age,gender) 每个对象都应该有自己的值

                但是有些值对于每一个对象来说都是一样的,像各种方法,对于这些一样的值没必要重复的创建

 

  <script>



        class Person{
            name = "张三"
            age = 18

            sayHello(){
                console.log("我是" + this.name)
            }
        }


        const p = new Person()

        const p2 = new Person()

        /*
            所有的同类型对象他们的原型对象都是同一个
                也就意味着同类型的原型链是一样的

            原型的作用:
                原型就相当于是一个公共的区域,可以被所有该类实例访问
                这样我们只需要创建一个属性,都可以被所有实例访问

            JS中继承就是通过原型来实现的
                当继承时,子类的原型就是父类的实例

            在对象中,有些值是对象独有的,像属性(name,age,gender) 每个对象都应该有自己的值
                但是有些值对于每一个对象来说都是一样的,像各种方法,对于这些一样的值没必要重复的创建
        */


        // 结果为true ,所有的同类型对象他们的原型对象都是同一个
        console.log(p.__proto__ === p2.__proto__)


        class Animal{

        }

        class Cat extends Animal{

        }

        const cat = new Cat()

        //   当继承时,子类的原型就是父类的实例
        // cat的原型是父类Animal实例, 父类Animal的原型object,object的原型为Object,Object原型为null
        console.log(cat)
        console.log("cat的原型" + cat.__proto__)
        console.log("父类Animal的原型" + cat.__proto__.__proto__)
        console.log("object的原型为" + cat.__proto__.__proto__.__proto__)
        console.log("Object原型为" + cat.__proto__.__proto__.__proto__.__proto__)
    </script>

八十四、JavaScript——修改原型

   大部分情况下,我们不需要修改原型对象

            注意:

                千万不要通过类的实例去修改原型

                    1. 通过一个实例去影响所有的同类对象,这么做不合适

                    2. 修改原型得先创建实例,麻烦

                    3. 危险

                除了通过__proto__能访问对象的原型外,

                    还可以通过类的prototype属性,来访问实例的对象: 类.prototype

                    修改原型,最好还是通过类去修改

                    好处:

                        1. 已修改就是修改所有实例的原型

                        2. 无需创建实例即可完成对类的修改

                    原则:

                        1. 原型尽量不要修改

                        2. 要改也不要通过实例对象修改

                        3. 通过 类.prototype 去修改

                        4. 最好不要直接给prototype去赋值 如:Person.prototype = { }

 <script>


        /*
            大部分情况下,我们不需要修改原型对象
            注意: 
                千万不要通过类的实例去修改原型
                    1. 通过一个实例去影响所有的同类对象,这么做不合适
                    2. 修改原型得先创建实例,麻烦
                    3. 危险

                除了通过__proto__能访问对象的原型外,
                    还可以通过类的prototype属性,来访问实例的对象: 类.prototype
                    修改原型,最好还是通过类去修改
                    好处:
                        1. 已修改就是修改所有实例的原型
                        2. 无需创建实例即可完成对类的修改
                    原则:
                        1. 原型尽量不要修改
                        2. 要改也不要通过实例对象修改
                        3. 通过 类.prototype 去修改
                        4. 最好不要直接给prototype去赋值 如:Person.prototype = { }


        */

        
        class Person{
            name = "张三"
            age = 18

            sayHello(){
                console.log("我是" + this.name)
            }
        }

        const p = new Person()

        const p2 = new Person()

        // 通过对象修改原型,向原型中添加方法,修改后所有的同类实例都能访问该方法
        
        p.__proto__.run = () => {
            console.log("我在跑")
        }

        p.__proto__ = new Dog()  // 直接为对象赋值了一个新的原型,不要这么做


        console.log(Person.prototype)  // 访问Person实例的原型对象

        p.run()
        p2.run()
        
    </script>

八十五、JavaScript——instanceof和hasOwn

            instanceof 用来检查一个对象是否是一个类的实例

                - instanceof 检查的是对象的原型链上是否有该类实例

                    只要原型链上有该类实例,就会返回true

                -

                    dog -> Animal的实例 -> Object实例 -> Object原型

               

                - Object是所有对象的原型,所以任何和对象和Object进行instanceof运算都会返回true

    in

                - 使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回true

            对象.hasOwnProperty(属性名)(不推荐使用)

                - 用来检查一个对象的自yong身是否含有某个属性

            Object.hasOwn(对象,属性名) (推荐使用)

                - 用来检查一个对象的自yong身是否含有某个属性

  <script>


        class Animal{

        }

        class Dog extends Animal{

        }

        const dog = new Dog()


        /*
            instanceof 用来检查一个对象是否是一个类的实例
                - instanceof 检查的是对象的原型链上是否有该类实例
                    只要原型链上有该类实例,就会返回true

                - 
                    dog -> Animal的实例 -> Object实例 -> Object原型
                
                - Object是所有对象的原型,所以任何和对象和Object进行instanceof运算都会返回true
        */

        // 通过instanceof检查dog是否是Dog类的实例
        console.log(dog instanceof Dog)  // true

        console.log(dog instanceof Animal) // true

        console.log(dog instanceof Object) // true



        // 读取实例原型的两种方式
        const obj = new Object()

        //方式一:通过对象访问Object原型
        console.log(obj.__proto__)

        //方式二:直接通过类访问Object原型
        console.log(Object.prototype)



        class Person{
            name = "张三"
            age = 18

            sayHello(){
                console.log("我是" + this.name)
            }
        }

        const p = new Person()

        /*
            in 
                - 使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回true

            对象.hasOwnProperty(属性名)(不推荐使用)
                - 用来检查一个对象的自yong身是否含有某个属性

            Object.hasOwn(对象,属性名) (推荐使用)
                - 用来检查一个对象的自yong身是否含有某个属性
        */
        
        // 检查 p 对象中是否含有 name 这个属性
        console.log("name" in p)

        // 检查 p 对象中是否含有 sayHello 这个属性
        console.log(p.hasOwnProperty("sayHello"))



    </script>

八十七、JavaScript——new运算符

new运算符是创建对象时要使用的运算符

                -new的解释 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

                - 当使用new去调用一个函数时,这个函数会作为构造函数调用

                    使用new调用函数时,会发生这些事

                    1. 创建一个普通的JS对象(Object对象 { }),为了方便,称其为新对象

                    2. 将构造函数的prototype属性设置为新对象的原型

                    3. 使用实参来执行构造函数,并且将新对象设置为函数中的this

                    4. 如果构造函数返回的是一个非原始值,则该值回作为new运算符的返回值返回

                        如果构造函数的返回值是一个原始值或者没有指定返回值

                            则新的对象会作为返回值返回

八十八、JavaScript——对象总结

 面向对象本质就是,编写代码时所有的操作都是通过对象来进行的

                面向对象的编程的步骤:

                    1. 找对象

                    2. 搞对象

                学习对象:

                    1. 明确对象代表什么,有什么用

                    2. 如何获取到这个对象

                    3. 如何使用这个对象(对象中的属性方法)

                对象的分类:

                内建对象    

                    - 由ES标准所定义的对象

                    - 比如:Object Function String Number。。。

                宿主对象

                    - 由浏览器提供的对象

                    - BOM DOM

               

                自定义对象

                    - 由开发人员自己创建的对象

猜你喜欢

转载自blog.csdn.net/z972065491/article/details/128467966