一定要懂 面向对象、内置对象、原型对象

114 阅读3分钟

面向对象

是一种 解决问题的思维方式

  1. 面向过程: 注重的是过程
    2.面向对象: 注重的是结果 举例 :
   /* 
        1. 面向对象 : 是 一种解决问题 思维方式
            面向过程 : 注重的是过程
            面向对象 : 注重的是结果

        2. 面向对象 本质 是对面向过程的封装
        */

        /* 举例:要吃火锅 */
        /*1.面向过程:注重过程 
        (1)买鸳鸯锅
        (2)买电磁炉
        (3)买锅底
        (4)买牛肉、羊肉、青菜、千张、毛肚、火锅面、菌类
        (5)开火热锅
        (6)放食材
        (7)夹起来开干
         */

        /* 2.面向对象:注重结果 
        点火锅送过来
        */

代码:

 /* 1.面向过程 : 注重过程 
        特点:代码冗余
        */

      //1.1 获取元素
      let divList = document.querySelectorAll("div")
      let pList = document.querySelectorAll("p")
      //1.2 遍历数组
      //   for (let i = 0; i < divList.length; i++) {
      //     divList[i].style.backgroundColor = "red"
      //     divList[i].style.border = "2px solid cyan"
      //   }

      //   for (let i = 0; i < pList.length; i++) {
      //     pList[i].style.backgroundColor = "blue"
      //     pList[i].style.border = "5px solid purple"
      //   }

      /* 2.面向对象
        函数封装 : 把冗余代码放入函数中(弊端:全局变量污染)
            全局变量污染 : 变量名太多,导致增加重名的风险,代码会被覆盖
        对象封装: 把函数作为对象的方法
      */
      let obj = {
        setColor: function(list, color) {
          for (let i = 0; i < list.length; i++) {
            list[i].style.backgroundColor = color
          }
        },
        setBorder: function(list, border) {
          for (let i = 0; i < list.length; i++) {
            list[i].style.backgroundColor = border
          }
        }
      }

      obj.setColor( divList, "red")
      obj.setColor(pList, "cyan")

数组对象api 语法

  <script>
        /*  一定要练习哟,不然学完就会忘

        内置对象:  js作者提前写好的对象,开发者直接拿来使用即可
        
        */ 
        
        //声明数组
        let arr = [10,20,30]

        //1. arr.concat( 数组 ) : 连接数组,得到一个连接后的新数组
        //应用场景 :  下拉加载更多的时候。 会把新数组 连接到原来数组的后面。
        arr = arr.concat(  [40,50,60] )
        console.log(arr)//[10,20,30,40,50,60]

        //2. arr.join('分隔符') : 把数组每一个元素拼接成字符串
        //应用场景 :  歌手不止一个,服务器会给你一个数组.  
        // ['周杰伦','蔡依林'].join('&')  '周杰伦&蔡依林'
        let str = arr.join('')
        console.log(str)

        //3. reverse() :  翻转数组
        //应用场景 :  电商类   销量、价格、距离 点击之后就会翻转显示
        arr.reverse( )
        console.log(arr)

        //4. arr.sort( function(a,b){ return a-b } ) : 数组排序

        let numArr = [20,8,50,66,90,35]

        numArr.sort( function(a,b){
            // return a-b//从小到大
            return b-a//从大到小
        } )

        console.log( numArr )
    
    </script>

字符串对象api

 <script>
        /* 一定要练习哟,不然学完就会忘记 */

        let str = '黑马程序员武汉大前端颜值担当就是ikun!'    

        //1.字符串类似于数组,也有长度 + 下标
        console.log( str.length )
        console.log( str[2] )//程

        //2. str.indexOf('字符串')   :  返回 字符串 在str中的首字符下标
        // 如果存在,则返回首字符下标。  如果不存在,则会返回固定值-1
        // 应用 : 检测字符串在不在str中
        
        let index1 = str.indexOf('武汉')
        console.log( index1 )//5

        let index2 = str.indexOf('干饭')
        console.log( index2 )//-1

        let index3 = str.indexOf('黑大')
        console.log(index3)//-1

        //3. str.split('分隔符')  : 把str按照分隔符切割成一个数组
        //应用: 切换url网址

        let url = 'http://wwww.baidu.com?username=dsgsdf&password=123456'

        let arr1 = url.split('?')
        console.log(arr1)//['http://wwww.baidu.com', 'username=dsgsdf&password=123456']

        let arr2 = url.split('=')
        console.log(arr2)//['http://wwww.baidu.com?username', 'dsgsdf&password', '123456']

        //4. str.substr(起始位置,截取长度)  : 截取部分字符串

        console.log( str.substr(10,4) )//颜值担当 从第10下标开始,截取4个字

        //5.大小写转换 : 中文没有大小写
        console.log( 'afasSFSasd'.toLocaleUpperCase() )//大写 AFASSFSASD
        console.log( 'afasSFSasd'.toLocaleLowerCase() )//小写 afassfsasd
      
    </script>

构造函数

<script>
        /* 学习总结
        1.工厂函数(了解概念) :  用于创建对象的函数

        2.构造函数 : 使用new关键字调用一个函数
            * 构造函数作用: 与工厂函数一致,用于创建对象

        3.new关键字工作原理(重点) :
            (1)创建空对象
            (2)this指向这个对象
            (3)对象赋值
            (4)返回这个对象

        4.new关键字注意点(拓展) :
            (1)构造函数首字母一般大写, 为了提醒调用者记得加new
            (2)如果手动在构造函数内部return
                return 值类型 :  无效,还是返回new创建对象
                return 引用类型 : 有效,会覆盖new创建的对象
        */

        /* 需求 :  需要创建很多个对象 (姓名、年龄、性别) */


        //封装函数解决代码冗余 

        function createPerson(name,age,sex){
            //(1)创建空对象   {}
            //(2)this指向这个对象  this={}
            //(3)对象赋值
            this.name = name
            this.age = age
            this.sex = sex
            //(4)返回这个对象  return this
            // return 666  //无效
            // return [10,20,30]  //有效
        }

        //构造函数
        let p1 = new createPerson('pink',18,'男')
        console.log( p1 )


        // function fn(){
        //     //(1)创建空对象
        //     //(2)自动返回对象
        // }

        // let f1 = fn()//普通函数
        // let f2 = new fn()//构造函数

        // console.log( f1,f2)
        
    </script>

原型对象构造资源浪费

/*
    1.原型对象是什么?
    2.原型对象作用?
    3.原型对象相关三个属性
    */


    //(1)了解构造函数内部方法 :  浪费内存资源

    // function Person(name,age){
    //   this.name = name
    //   this.age = age
    //   this.eat = function(){
    //     console.log('吃东西')
    //   }
    // }

     /* p1和p2都有eat方法,并且代码一致。但是他们是同一个方法吗?
    答案: 不是.  因为p1和p2的eat虽然代码是一致的,但是它们两个函数在堆中是两个不同的堆地址。
    知识易错误区:  引用类型只比较地址,不比较值。 不能因为值相同,就认为引用类型地址相同
    */
    // console.log(p1.eat == p2.eat)//false

    //(2)使用全局函数: 解决内存浪费
    //弊端; 造成变量污染

    //(3)使用对象 : 解决内存浪费 + 变量污染 
    //唯一问题: obj本身成为了唯一的污染

    const obj = {
      eat: function () {
        console.log('吃东西')
      },
      learn: function () {
        console.log('学习')
      }
    }

    function Person(name, age) {
      this.name = name
      this.age = age
      this.eat = obj.eat
      this.learn = obj.learn
    }

    let p1 = new Person('ikun', 30)
    let p2 = new Person('班长', 30)

    console.log(p1, p2)
   
    console.log(p1.eat == p2.eat)//true

原型对象

/* 
        1.原型对象是什么? :  任何函数被创建的时候,系统会自动创建一个对应的对象,称之为原型对象
        2.原型对象作用? :  内存浪费 + 变量污染
        3.原型对象相关三个属性 : 描述 构造函数、原型对象、 实例对象 三者关系
        */

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

        //2.原型对象
        Person.prototype.eat = function(){
          console.log('吹东西')
        }

        Person.prototype.learn = function(){
          console.log('学习')
        }

        //3.实例对象
        let p1 = new Person('ikun',30)
        let p2 = new Person('班长',30)

        console.log(p1,p2)

        p1.eat()

        p2.learn()

__proto__属性

  <script>
        /* 
        1.原型对象是什么? :  任何函数创建的时候,系统会自动创建一个对象,称之为原型
        2.原型对象作用? : 解决内存浪费 + 变量污染
        3.原型对象相关三个属性 : 描述 构造函数、原型对象、 实例对象 三者关系
            prototype : 属于构造函数,指向原型对象
            __proto__ : 属于实例对象,指向原型对象       
        */    

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

        //2.原型对象
        Person.prototype.eat = function(){
            console.log('吃东西')
        }

        //3.实例对象
        let p1 = new Person('班长',30)
        console.log( p1 )

        /* 
        __proto__ : 属于实例对象,指向原型
            实际开发中,__proto__不能使用的。因为不是ECMA标准语法
            学习阶段,为了理解原型,可以适当使用
        */
        p1.eat()//p1.__proto__.eat()
        

    </script>

constructor属性

 <script>
        /* 
        1.原型对象是什么? :  任何函数创建的时候,系统会自动创建一个对象,称之为原型
        2.原型对象作用? : 解决内存浪费 + 变量污染
        3.原型对象相关三个属性 : 描述 构造函数、原型对象、 实例对象 三者关系
            prototype : 属于构造函数,指向原型对象
                * 作用: 解决构造函数内存浪费+变量污染
            __proto__ : 属于实例对象,指向原型对象
                * 作用:  让实例对象直接使用原型的成员(函数+属性)
            constructor : 属于原型对象,指向构造函数  
                * 作用 : 让实例对象知道自己的构造函数是谁  
        */    

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

        //2.原型对象
        Person.prototype.eat = function(){
            console.log('吃东西')
        }

        /* constructor : 属于原型对象,指向构造函数  
            作用: 可以让实例对象知道自己被哪一个构造函数创建
        */
        console.log( Person.prototype.constructor )//Person
        
        //3.实例对象
        let p1 = new Person('班长',30)
        console.log( p1 )

    
        //查看p1的原型

        console.log( p1.__proto__.constructor )//Person
        console.log( p1.__proto__ === Person.prototype )//true
        
    </script>

动态成员与实例成员

<script>
        /* 
        静态成员:  函数自己的成员
        实例成员:  实例对象的成员

        小节:  .的左边是函数,就是静态成员。 左边是实例对象,就是实例成员。
        */


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

        //2.原型对象
        Person.prototype.eat = function () {
            console.log('吃东西')
        }


        //3.实例对象
        let p1 = new Person('班长', 30)
        console.log(p1)


        console.log( Person.prototype )//静态
        console.log( p1.name )//实例

        console.log( Math.PI )//静态

    </script>

-Object的values方法

<script>
        
         /* 需求:获取对象所有的属性值 */   
         let person = {
             name:'张三',
             age:20,
             sex:'男'
         }

         //以前 : for-in
         //对象.属性名   对象[ 变量 ]
         for(let key in person){
             console.log( person[key] ) 
         }

         /* 常用的静态成员 : Object.values(对象名) */
         console.log( Object.values(person) )//['张三', 20, '男']
         console.log( Object.keys(person) )//['name', 'age', 'sex']
         
    </script>