JS高级

01-面向对象三大特征(继承)

1.1-面向对象三大特征介绍

​ a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现(前面学习的api其实就是一种封装思想)
​ b.继承:一个对象拥有其他对象的属性和方法
​ c.多态:一个对象在不同情况下的多种状态(java语言使用较多,js语言基本不涉及)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<script>
    /*面向对象三大特征
        a.封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
        b.继承:一个对象拥有其他对象的属性和方法
        c.多态:一个对象在不同情况下的多种状态
     */


    /*多态(了解即可,使用不多):一个对象在不同情况的多种状态
        饲养员对象Person : 给动物对象喂养食物  funtion work(animal,food){ animal.eat(food) }
        动物对象Animal : 吃东西  eat(food){ }
        多态 : 给不同的动物喂养食物,虽然都是调用eat()方法,但是不同的动物会执行不同的eat()
    */
    //示例:饲养员给动物喂食物
    
    //动物
    function Animal ( name ) {
        this.name = name;
    };

    //猫
    let cat = new Animal('猫咪');
    cat.eat = function ( food ) {
        console.log ( "喵喵猫" + "我吃了" + food );
    };

    //狗
    let dog = new Animal('小狗狗');
    dog.eat = function ( food ) {
        console.log ( "汪汪汪" + "我吃了" + food );
    };

    //饲养员
    function Person (  name ) {
        this.name = name;
    };
    Person.prototype.work = function (animal,food ) {
        //animal接收一个由Anmiaml构造函数生成的实例化对象,调用它的eat方法
        //同一对象表现出来不同的状态,就叫做多态
        animal.eat(food);
    };

    let p1 = new Person('ikun');
    p1.work(cat, '饼干');
    p1.work(dog, '翔');


</script>
</body>
</html>

1.2-替换原型继承

  • 继承:让一个对象拥有另一个对象的属性和方法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        
        
        //父对象
       let father = {
           house : {
               address:'武汉天地',
               price : 10000000
           },
           car:{
               brand:'劳斯莱斯幻影',
               price:8000000
           }
       }

       //子对象构造函数
       function Son(name,age){
        this.name = name
        this.age = age
       }

       //默认原型
       Son.prototype.eat = function(){
           console.log('吃东西')     
       }
       /* 替换原型继承: 把父对象作为子对象构造函数的原型*/
       Son.prototype = father

       let son1 = new Son('爽哥',20)
       let son2 = new Son('ikun',30)
       console.log(son1,son2)
       
    </script>
</body>
</html>

02-原型链

1.1-原型链介绍

  • 本小节知识点
    • 1.原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链
    • 2.对象访问原型链中的成员规则:就近原则
      • 当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:xxx is not a function
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>

        /* 
        1.原型链 :每一个对象,都有__proto__指向自身的原型。 而原型也是对象,也有自己的
        __proto__指向原型的原型,以此类推形成链式结构,称之为原型链。

        2.对象访问原型链中成员的规则 :就近原则
            当访问对象的成员,先看自己有没有。有则访问,没有则看原型有没有。原型有则访问,
            没有则访问原型的原型,没有则继续往上找。以此类推,一直找到原型链终点 : null.
            还没有, 如果是属性 : 则获取undefined  如果是方法 ,则报错xxx is not defined 
         */
        
        //1.构造函数
        function Person(name,age){
            this.name = name;
            this.age = age;
        };

        //2.原型对象
        Person.prototype.sayHi = function(){
            console.log('人生若只如初见,何事秋风悲画扇');
        };

        Person.prototype.type = '哺乳动物';

        //3.实例化对象
        let p1 = new Person('又又',18);
        console.log(p1);

        //请说出以下代码执行结果
        console.log(p1.name);//又又      p1自己有name属性
        console.log(p1.type);//哺乳动物   p1自己没有type,但是p1的原型有
        console.log(p1.hobby);//undefined p1自己没有hobby,原型也没有
        p1.sayHi();// 人生若只如初见,何事秋风悲画扇   p1自己没有这个方法,原型有
       // p1.eat();//报错 xxx is not defined    p1自己没有这个方法,原型也没有

       //为什么不报错?  p1自己没有这个方法,原型也没有这个方法,但是原型的原型有
        p1.toString();

        //查看p1的原型链
        console.log(p1.__proto__.constructor);//Person
        console.log(p1.__proto__ === Person.prototype);//true

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

        //查看p1的原型的原型的原型
        console.log(p1.__proto__.__proto__.__proto__);//null

    </script>
</body>
</html>

1.2-原型链详解:内置对象的原型链

  • 本小节知识点:内置对象的原型链(附图解说明)
    • 1.通过查看Array的原型链
      • 了解构造函数的原型本身是一个对象,只要是对象就有原型
    • 2.通过查看Date的原型链
      • 学会举一反三,所有的内置对象(Math Array 基本包装类型等)的原型链都是一样的,最终都指向Object
    • 3.通过查看String的原型链:了解这里的String值得是内置对象String(是一个基本包装类型),其他的Number、Boolean原型链和String是一样的
      • 只有对象才有原型,这里一定要把基本数据类型string、number、boolean,和基本包装类型(特殊的引用类型对象)String、Number、Boolean区分开来,不要搞混淆
  • 思考题:为什么arr.toString()方法和对象的toString()方法得到的结果不同

1.Array的原型链

//1.Array
    let arr = new Array(10,20,30);
    console.log ( arr );
    //查看arr的原型
    console.log ( arr.__proto__.constructor );//Array
    console.log ( arr.__proto__ === Array.prototype );
    //查看arr的原型的原型
    console.log ( arr.__proto__.__proto__.constructor );//Object
    console.log ( arr.__proto__.__proto__ === Object.prototype );//true

2-Date的原型链

//2.Date
    let date1 = new Date();
    //细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
    console.dir(date1);
    console.log ( date1.__proto__ === Date.prototype );//true
    console.log ( date1.__proto__.__proto__.constructor );//Object
    console.log ( date1.__proto__.__proto__ === Object.prototype );//true

3-String对象原型链

//3.String
    let str = new String('123');
    console.log ( str );
    console.log ( str.__proto__ === String.prototype );//true
    console.log ( str.__proto__.__proto__.constructor );//Object
    console.log ( str.__proto__.__proto__ === Object.prototype );//true

4-DOM对象原型链

//4.界面元素
    let div1 = document.getElementById('div1');
    let p1 = document.getElementById('p1');

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkgNQIm7-1650269840450)(day02.assets/1559057534710.png)]

  • 完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="div1"></div>
<p id="p1"></p>

<script>
    /*查看内置对象的原型链*/

    //1.Array
    let arr = new Array(10,20,30);
    console.log ( arr );
    //查看arr的原型
    console.log ( arr.__proto__.constructor );//Array
    console.log ( arr.__proto__ === Array.prototype );
    //查看arr的原型的原型
    console.log ( arr.__proto__.__proto__.constructor );//Object
    console.log ( arr.__proto__.__proto__ === Object.prototype );//true

    //2.Date
    let date1 = new Date();
    //细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
    console.dir(date1);
    console.log ( date1.__proto__ === Date.prototype );//true
    console.log ( date1.__proto__.__proto__.constructor );//Object
    console.log ( date1.__proto__.__proto__ === Object.prototype );//true

    //3.String
    let str = new String('123');
    console.log ( str );
    console.log ( str.__proto__ === String.prototype );//true
    console.log ( str.__proto__.__proto__.constructor );//Object
    console.log ( str.__proto__.__proto__ === Object.prototype );//true

    //4.界面元素
    let div1 = document.getElementById('div1');
    let p1 = document.getElementById('p1');

</script>
</body>
</html>

1.3-instanceof运算符

本小节知识点

  • instanceof语法: 对象 instanceof 构造函数
  • 作用:检测构造函数的原型prototype在不在这个对象的原型链上
	//1.示例
    let arr = [10,20,30];
    //数组原型链  arr->Arr.prototype->Object.prototype->null
    console.log ( arr instanceof Array );//true
    console.log ( arr instanceof Object );//true

    //2.示例
    //根据instanceof语法:左边Function表示对象,右边Function表示构造函数
    //Function原型链  Function对象->Function.prototype->Object.prototype->null
    console.log ( Function instanceof Function );//true
    console.log ( Function instanceof Object );//true

    //3.示例
    //根据instanceof语法:左边Object表示对象,右边Object表示构造函数
    //Object原型链 Object对象->Function.prototype->Object.prototype->null
    console.log ( Object instanceof Object );//true
    console.log ( Object instanceof Function );//true

03-原型链应用:封装模态框

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>面向对象封装消息提示</title>
    <style>
      .modal {
        width: 300px;
        min-height: 100px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
        border-radius: 4px;
        position: fixed;
        z-index: 999;
        left: 50%;
        top: 50%;
        transform: translate3d(-50%, -50%, 0);
        background-color: #fff;
      }
      .modal .header {
        line-height: 40px;
        padding: 0 10px;
        position: relative;
        font-size: 20px;
      }
      .modal .header i {
        font-style: normal;
        color: #999;
        position: absolute;
        right: 15px;
        top: -2px;
        cursor: pointer;
      }
      .modal .body {
        text-align: center;
        padding: 10px;
      }
      .modal .footer {
        display: flex;
        justify-content: flex-end;
        padding: 10px;
      }
      .modal .footer a {
        padding: 3px 8px;
        background: #ccc;
        text-decoration: none;
        color: #fff;
        border-radius: 2px;
        margin-right: 10px;
        font-size: 14px;
      }
      .modal .footer a.submit {
        background-color: #369;
      }
    </style>
  </head>
  <body>
    <button id="btn1">消息提示1</button>
    <button id="btn2">消息提示2</button>
    <button id="btn3">消息提示3</button>


    <!-- <div class="modal">
      <div class="header">提示消息 <i>x</i></div>
      <div class="footer">
        <img src="./111.jpg" alt="" width="80%">
      </div>
    </div> -->
    

    <script>
      //1.模态框构造函数
      function Modal(title, url) {
        //标题
        this.title = title
        //内容
        this.url = url
        //dom文本
        this.modalBox = `<div class="modal">
        <div class="header">${this.title}<i>x</i></div>
        <div class="footer">
          <img src="${url}" alt="" width="100%">
        </div>
        </div>`
      }

      //2.模态框原型
      //2.1 显示模态框
      Modal.prototype.open = function() {
        //(1)创建空标签
        let div = document.createElement('div')
        //(2)设置内容
        div.innerHTML = this.modalBox
        //(3)添加到页面
        document.body.appendChild(div)

        //给xx按钮注册一个移除事件
        div.querySelector('.header i').onclick = function(){
          document.body.removeChild(div)
        }
      }



      /* 点击按钮 */

      //按钮1
      document.querySelector('#btn1').onclick = function(){
        let confirm = new Modal('提示消息','./111.jpg')
        //展示
        confirm.open()
      }

      //按钮2
      document.querySelector('#btn2').onclick = function(){
        let confirm = new Modal('友情提示','./222.jpg')
        //展示
        confirm.open()
        
      }

      //按钮3
      document.querySelector('#btn3').onclick = function(){
        let confirm = new Modal('友情提示','./333.jpg')
        //展示
        confirm.open()
        
      }

      
    </script>
  </body>
</html>

04-函数补充(了解即可)

1.1-arguments关键字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
        1.arguments关键字: 获取函数所有实参
            * 是一个伪数组
            * 只能用于函数
        2.场景 : 例如数组push()方法,传多少实参就给数组添加多少元素。底层原理就是使用arguments实现的
         */

         function fn(){
            console.log(arguments)
         }

         fn(10,20,30,40)
    </script>
</body>
</html>

1.2-剩余参数(rest参数)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
        1.剩余参数(rest参数) : 获取函数剩余的所有实参
            * 是一个真数组
            * 只能写在函数最后形参位置
        2.场景:大多数情况下, rest参数可以替代arguments
            arguments是老语法,浏览器兼容性好
            rest参数:新语法,有些老的浏览器不支持
         */

         function fn(a,b,...c){
            console.log(arguments)//获取所有实参 10 20 30 40
            console.log(a,b)//10 20
            console.log(c)//[30,40] 获取剩余参数
         }

         fn(10,20,30,40)
    </script>
</body>
</html>

1.3-函数默认参数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        /*函数默认参数 
            ES5 : 逻辑或短路
                * 逻辑或口诀: 一真则真
                * 逻辑或短路口诀 : 找真.  左边为真就是左边的结果,否则右边的结果
            ES6 :  形参=默认值
        */

        function fn(a, b = 20) {
            // b = b || 20
            console.log(a)
            console.log(b)//如果b是undefined, 则 a + b = NaN
            //10 + Number(undefined) = 10 + NaN = NaN
            console.log(a + b)
        }

        fn(10,5)
        fn(10)

    </script>
</body>

</html>

1.4-变量声明let与const

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /* 声明变量关键字
        1. ES5声明变量 var 
            1.1 有变量预解析
            1.2 没有块级作用域

        2.ES6声明变量 let const
            1.1 没有变量预解析
            1.2 有块级作用域

        3. let与const区别
            let : 变量。 可以修改
            const : 常量。 不可以修改
        * 实际开发中, 只要不修改的变量都用const,需要改的时候用let
      */

      //1. ES5声明变量 var
      // 1.1 预解析 :  变量的声明会提升到当前作用域最顶端
      console.log(num)
      var num = 10

      /* 
        var num
        console.log( num )
        num = 10
      */

      //1.2 没有块级作用域 :
      for (var i = 1; i <= 5; i++) {}
      console.log(i)

    </script>
  </body>
</html>

1.5-for-in与for-of区别(面试点)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        /* for-in与for-of区别 
        1.功能不同
            for-in是遍历数组的下标
            for-of是遍历数组的元素
        2.原型的属性
            for-in会遍历原型的属性
            for-of不会遍历原型的属性
        3.数据类型
            for-in可以遍历Object类型
            for-of不可以遍历Object类型
        
        总结:如果只想要属性值/元素,使用for-of效率更高
        */

        //数组
        let arr = ['a','b','c']//下标0 1 2
        //给原型添加成员
        Array.prototype.age = 30

        //对象
        let obj = {name:'ikun',age:30}
        

        //遍历数组
        //for-in
        for(let key in arr){
            console.log(key,arr[key])//下标,元素
        }
        //for-of
        for (let item of arr ) {
            console.log(item)  //元素     
        }

        //遍历对象 : 程序报错
        // for (let item of obj ) {
        //     console.log(item)  //属性名    
        // }
   
    </script>
</body>
</html>

今天学习重点梳理(面试题)

  • 1.js语言是通过什么技术实现面向对象继承的

    • 答案:原型链
  • 2.原型链终点是什么

    • 答案:null
  • 3.for-in与for-of区别

    • 1.功能不同
      • for-in是遍历数组的下标
      • for-of是遍历数组的元素
    • 2.原型的属性
      • for-in会遍历原型的属性
      • for-of不会遍历原型的属性
    • 数据类型
      • for-in可以遍历Object类型
      • for-of不可以遍历Object类型

Array.prototype.age = 30

    //对象
    let obj = {name:'ikun',age:30}
    

    //遍历数组
    //for-in
    for(let key in arr){
        console.log(key,arr[key])//下标,元素
    }
    //for-of
    for (let item of arr ) {
        console.log(item)  //元素     
    }

    //遍历对象 : 程序报错
    // for (let item of obj ) {
    //     console.log(item)  //属性名    
    // }

</script>
```

今天学习重点梳理(面试题)

  • 1.js语言是通过什么技术实现面向对象继承的

    • 答案:原型链
  • 2.原型链终点是什么

    • 答案:null
  • 3.for-in与for-of区别

    • 1.功能不同
      • for-in是遍历数组的下标
      • for-of是遍历数组的元素
    • 2.原型的属性
      • for-in会遍历原型的属性
      • for-of不会遍历原型的属性
    • 数据类型
      • for-in可以遍历Object类型
      • for-of不可以遍历Object类型
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值