【总结】JavaScript - 对象的进阶

1. 面向对象

	面向对象是一种注重结果的思维方式

2. 面向对象与面向过程的关系

	面向对象的本质是对面向过程的封装

3. 构造函数创建对象(new关键字原理)

	1.创建空对象
	2.this指向这个对象
	3.对象的赋值
	4.返回这个对象

4. 原型对象

	1.原型对象:每一个函数创建的时候,系统都会自动创建一个与之对应的原型对象
	2.原型对象的作用:解决构造函数内存资源的浪费,和全局变量的污染
	3.原型对象的访问方式:    构造函数.prototype

5. 实例对象

	调用构造函数的对象
	实例对象可以访问原型对象中的一切
	constructor 属性:原型对象的属性  指向构造函数
	语法: 实例对象.constructor   
	作用:让实例对象知道是被那个构造函数创建的

6. 原型对象使用的注意点

	1.那些属性可以放入原型中
		所有实例对象共享的成员
	2.对象访问原型的规则   就近原则
		对象访问成员的时候  优先访问自身的  如果自身没有才会访问原型对象的
	3.原型对象是可以覆盖的
		实例对象访问覆盖前的原型对象还是访问覆盖后的原型对象  取决于实例对象的创建时间
			覆盖前创建的   指向覆盖前的原型
			覆盖后创建的   指向覆盖后的原型

7. 构造函数、原型对象、实例对象三者之间的三角关系

        prototype:属于构造函数,指向原型对象
        constructor:属于原型对象,指向构造函数
        __proto__:属于实例对象,指向原型对象

在这里插入图片描述

8. 面向对象三大特征

        封装
	    把需要复用的代码放入对象的方法
        继承
	    一个对象拥有另一个对象所有的成员(三种继承方式:混入式继承,替换原型继承,混合式继承)
        多态
	    一个对象在不同情况的多种状态

9. 三种继承方式

       1.混入式继承 : 遍历父对象成员添加给子对象         
        * 特点: 适用于一个子对象                  
       2.替换原型继承 : 将父对象作为子对象的原型          
        * 特点:可以实现多个子对象继承,但是会覆盖子对象默认的原型   
       3.混合式继承 : 混入式 + 替换原型             
        * 遍历父对象所有成员,添加给子对象的原型            
        * 特点: 可以实现多个子对象继承,并且不会覆盖子对象默认的原型 

10. 原型链

在这里插入图片描述

js是通过原型链实现继承的

 1.原型链: 对象有自己的原型,原型对象也是对象,也有自己的原型。以此类推形成链式结构,称之为原型链
 2.对象访问原型链规则: 就近原则
      先从自己找,自己没有从原型找,原型没有就找原型的原型。
      以此类推,直到原型链终点null.如果还没有,属性则获取undefined,方法则报错xxx is not a function    

11. 内置对象的原型链

arr 对象的原型链

        //声明数组对象    
        let arr = [10,20,30]//new Array(10,20,30)

        //1.查看arr对象的原型
        console.log( arr.__proto__.constructor )//Array
        console.log( arr.__proto__ === Array.prototype )//true
        
        //2.查看arr对象的原型的原型
        console.log( arr.__proto__.__proto__.constructor )//Object
        console.log( arr.__proto__.__proto__ === Object.prototype )//true
        
        /* js作者把数组所有的方法都会放在Array.prototype中
        这样的话所有的数组实例对象都可以继承原型中的方法(节省内存资源)
         js是通过原型链实现面向对象的继承
        */
        arr.reverse()

在这里插入图片描述

Date 对象的原型链

      //声明日期对象
      let d1 = new Date()
      /* js中有少部分的对象,无法通过log来打印的。 一旦使用log会自动转成字符串显示
            *  日期对象Date   函数对象function  DOM对象
        如果想要看这三个对象的内存,则需要使用 console.dir()
      */
      console.log(d1)
      console.dir(d1)

      //1.查看日期对象的原型
      console.log(d1.__proto__.constructor) //Date
      console.log(d1.__proto__ === Date.prototype) //true

      //2.查看日期对象的原型的原型
      console.log(d1.__proto__.__proto__.constructor )//Object
      console.log(d1.__proto__.__proto__ === Object.prototype )//true
      

在这里插入图片描述

String 对象的原型链

      //string对象
      let str = new String('abc') //new String('abc')
      console.log(str)

      //1.查看str的原型
      console.log( str.__proto__.constructor )//String
      console.log( str.__proto__ === String.prototype )//true

      //2.查看str的原型的原型
      console.log( str.__proto__.__proto__.constructor )//Object
      console.log( str.__proto__.__proto__ === Object.prototype )//true

在这里插入图片描述

DOM 对象的原型链

<body>
    <div class="box">我是div</div>
    <p class="pp">我是p标签</p>

    <script>
      let box = document.querySelector('.box')
      let pp = document.querySelector('.pp')

      console.log(box)
      console.dir(box)
      console.log(pp)
      console.dir(pp)

      console.log(box.__proto__)
      console.log(box.__proto__.__proto__)
      console.log(box.__proto__.__proto__.__proto__)
      console.log(box.__proto__.__proto__.__proto__.__proto__)
      console.log(box.__proto__.__proto__.__proto__.__proto__.__proto__)

    </script>
  </body>

在这里插入图片描述

函数对象的原型链

 /* 
        1.函数也是对象类型
            * 函数也有自己的原型链
        
        */

      //如何证明一个函数也是对象类型 : 使用点语法证明(对象才有点语法)
      function fn () {
        console.log('111111')
      }

      //如果函数也可以像对象那样使用点语法存储属性,说明函数也是对象类型
      fn.sex = '男'
      fn.age = 38

      console.log(fn) //只能打印代码
      console.dir(fn) //只能打印代码

      console.log(fn.sex) //男
      console.log(fn.age) //38

      //1.查看函数的原型链
      console.log(fn.__proto__.constructor)//Function
      console.log(fn.__proto__ === Function.prototype)//true
      //2.查看函数原型的原型
      console.log(fn.__proto__.__proto__.constructor)//Object
      console.log(fn.__proto__.__proto__ === Object.prototype)//true
      

在这里插入图片描述

12. instanceof 关键字

  1. 与原型链相关的关键字: instanceof
  2. instanceof运算符 : 对象 instanceof 构造函数
    • 检测右边构造函数的原型 在不在 左边实例对象的 原型链中
      //测试1
      // arr -> Array.prototype -> Object.prototype -> null
      let arr = [10, 20, 30]
      console.log(arr instanceof Array) //true
      console.log(arr instanceof Object) //true

      /* 任何函数原型链都是固定的(包含构造函数  fn、Person、Date、Array、Function、Object)
      函数  -> Function.prototype -> Object.prototype -> null
      */

      //测试2 : 左边的是函数对象  右边是  构造函数
      //Function实例对象  ->  Function.prototype -> Object.prototype -> null
      console.log(Function instanceof Function)//true
      console.log(Function instanceof Object)//true

      //测试3 : 左边的是函数对象  右边是  构造函数
      //Object实例对象  ->  Function.prototype -> Object.prototype -> null
      console.log(Object instanceof Function)//true
      console.log(Object instanceof Object)//true

13. 静态成员与实例成员

静态成员: 属于函数对象的成员

实例成员: 属于实例对象的成员

    //构造函数
      function Person (name, age) {
        this.name = name
        this.age = age
      }

      //实例对象
      let p1 = new Person('ikun', 32)
      //实例成员
      console.log(p1.name)
      console.log(p1.age)

      //静态成员
      Person.sex = '男'
      console.log(Person.sex)//'男'

      // 实例对象 只能访问自己的 和 原型的成员(实例成员)。
      //实例对象  不可以访问构造函数中的成员。(静态成员)
      console.log( p1.sex )//undefined

14. class关键字

class关键字作用 : 声明一个类函数

        * 类函数: 其实就是构造函数
        * 类函数好处:
            a. 把构造函数 和 原型 包在一个大括号内部,阅读性高
            b. 类函数必须使用new调用,不使用new

class关键字语法 :

           class 构造函数{
               //(1)必须要有一个函数叫做constructor
               constructor(name,age){
                   this.name = name
                   this.age = age
               }
               //(2)下面写原型中的成员
               eat(){   //等价于: Person.prototype.eat = function(){}
               }
           }

15. ES5构造函数与ES6类函数的区别

1 . ES5构造函数

      //构造函数
    //   function Person (name, age) {
    //     this.name = name
    //     this.age = age
    //   }
    //   //原型对象
    //   Person.prototype.eat = function () {
    //     console.log('我要吃饭')
    //   }
    //   //实例对象
    //   let p1 = new Person('班长', 38)
    //   console.log(p1)

2 . ES6类函数

      //类函数
      class Person {
        //构造函数
        constructor (name, age) {
          this.name = name
          this.age = age
        }
        //原型对象
        eat () {
          console.log('我要吃饭')
        }
      }

      //使用类函数,其实底层跟以前一模一样,以前的语法完全可以直接用
      Person.prototype.learn = function(){
          console.log('111');
      }
      Person.prototype.type = '中国人'

      //调用类函数
      let p2 = new Person('ikun', 32)
      console.log(p2)

16. extends关键字

1.作用 : 继承

2.原理 : 替换原型方式继承

3.语法 : class 子构造函数 extends 父构造函数

     //类函数
      class Person {
        //(1)构造函数
        constructor (name, age) {
          this.name = name
          this.age = age
        }
        //(2)原型对象
        eat () {
          console.log('我要吃饭')
        }
      }

      //(3)调用类函数 : 创建实例对象
      let p2 = new Person('ikun', 32)
      console.log(p2)

      /* 子构造函数
      底层原理不是替换Student的原型,而是替换Student原型的原型
      Student.prototype.__proto__ = Person.prototype
      */
      class Student extends Person {
        learn () {
          console.log('我爱学习')
        }
      }

      let s1 = new Student('班长', 38)
      console.log(s1)

在这里插入图片描述

17. super关键字

1.作用: 子类中调用父类的方法

2.原理: 函数上下文调用

3.语法 : super关键字只能用于extends中

       class Student extends Person {
        //想自己写构造函数
        constructor (name, age, score) {
          /* 当子类 继承 父类的时候,如果子类想要自己写构造函数。 
          就必须要在自己的构造函数中调用super()
           */
          super(name,age)
          this.score = score
        }
       } 

注意 : 如果子类也要写自己的构造函数, 就必须要先调用 super() 调用父类的构造函数

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疆子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值