前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端day18-JS高级(完整的原型链)学习笔记

前端day18-JS高级(完整的原型链)学习笔记

原创
作者头像
帅的一麻皮
修改2020-05-07 18:04:07
4680
修改2020-05-07 18:04:07
举报
文章被收录于专栏:前端与Java学习前端与Java学习

01-面向对象三大特征(封装、继承、多态)

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

1.1-多态(js中了解即可)

代码语言:javascript
复制
<script>
    /*多态(JS中了解即可,使用不多):一个对象在不同情况的多种状态
        饲养员对象Person : 给动物对象喂养食物  funtion work(animal,food){ animal.eat(food) }
        动物对象Animal : 吃东西  eat(food){ }
        多态 : 给不同的动物喂养食物,虽然都是调用eat()方法,但是不同的动物会执行不同的eat()
    */
    //示例:饲养员给动物喂食物
    
    //动物
    function Animal ( name ) {
        this.name = name;
    };
    //猫
    var cat = new Animal('猫咪');
    cat.eat = function ( food ) {
        console.log ( "喵喵猫" + "我吃了" + food );
    };
    //狗
    var 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);
    };

    var p1 = new Person('林绿裙');
    p1.work(cat, '饼干');
    p1.work(dog, '翔');


</script>

1.2-继承(三种实现方式)
  • 1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
    • 特点:每继承一次,就要执行一次循环
    • 应用场景:单个对象继承
  • 2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
    • 特点:会丢失原型之前的成员变量
    • 应用场景:多个对象继承
  • 3.混合式继承 : 混入式 + 替换原型
    • 特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型

代码语言:javascript
复制
<script>
​
    /*学习目标 : 继承的三种实现方式 
        1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象
            特点:每继承一次,就要执行一次循环
            应用场景:单个对象继承
​
        2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型
            特点:会丢失原型之前的成员变量
            应用场景:多个对象继承
​
        3. 混合式继承 : 混入式 + 替换原型
            特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型
​
     */
    //继承:让一个对象拥有另一个对象的属性和方法
    var wangjianlin = {
        house:{
            address:'北京一环',
            price:100000000
        },
        car:{
            brand:'劳斯莱斯',
            price:5000000
        }
    };
    var wangsicong = {
        girlFriends:['雪梨','豆得儿','林更新','王建刚','赵铁柱']
    };
    //wangsicong这个对象想要继承wangjianlin这个对象的属性和方法
​
    //1.混入式
    //解决方案:遍历wangjianlin的所有属性值,添加给wangsicong对象
    //特点:每继承一次,就要执行一次循环
    //应用场景 : 单个对象继承
/*
    for (var key in wangjianlin){
        wangsicong[key] = wangjianlin[key];
    }
    console.log ( wangsicong );
*/
​
    //2.替换原型
    //解决方案:将wangjianlin对象作为构造函数的原型
    //特点:会丢失原型之前的成员变量
    //应用场景:多个对象继承
/*
    function SonWang (name,gfs  ) {
        this.name = name;
        this.gfs = gfs;
    };
    //每一个SonWang构造函数实例化的对象都有一个花钱的方法,那这个方法就可以写在原型中
    SonWang.prototype.flowerMoney = function (  ) {
        console.log ( "我很会花钱哄女孩子吃六块钱的麻辣烫…………" );
    }
​
    //让wangjianlin对象成为SonWang构造函数的原型,所有SonWang构造的实例化对象都可以访问wangjianlin的成员变量
    SonWang.prototype  = wangjianlin;
​
    //实例化对象
    var son1 = new SonWang('聪聪',['雪梨','豆得儿','林更新','王建刚','赵铁柱']);
    console.log ( son1 );
    var son2 = new SonWang('班长',['苍老师','吉泽老师','结衣老师','白石老师']);
    console.log ( son2 );
*/
​
​
    //3.  混合式(混入+替换原型)
    //解决方案:遍历wangjianlin对象所有的属性值,添加给构造函数的原型
    function SonWang (name,gfs  ) {
        this.name = name;
        this.gfs = gfs;
    };
    //每一个SonWang构造函数实例化的对象都有一个花钱的方法,那这个方法就可以写在原型中
    SonWang.prototype.flowerMoney = function (  ) {
        console.log ( "我很会花钱哄女孩子吃六块钱的麻辣烫…………" );
    }
​
   //将wangjianlin对象的所有属性添加到SonWang构造函数的原型中
    for(var key in wangjianlin){
        SonWang.prototype[key] = wangjianlin[key];
    }
​
    //实例化对象
    var son1 = new SonWang('聪聪',['雪梨','豆得儿','林更新','王建刚','赵铁柱']);
    console.log ( son1 );
    var son2 = new SonWang('班长',['苍老师','吉泽老师','结衣老师','白石老师']);
    console.log ( son2 );
</script>

1.3-混合式继承函数封装

代码语言:javascript
复制
/**混合式继承
     *
     * @param method 要继承的子对象构造函数
     * @param father 被继承的父对象
     */
    function extend (method,father  ) {
        for(var key in father){
            method.prototype[key] = father[key];
        }
    }

//继承:让一个对象拥有另一个对象的属性和方法
    var wangjianlin = {
        house:{
            address:'北京一环',
            price:100000000
        },
        car:{
            brand:'劳斯莱斯',
            price:5000000
        }
    };
    var wangsicong = {
        girlFriends:['雪梨','豆得儿','林更新','王建刚','赵铁柱']
    };
    //wangsicong这个对象想要继承wangjianlin这个对象的属性和方法
    //解决方案:遍历wangjianlin对象所有的属性值,添加给构造函数的原型
    function SonWang (name,gfs  ) {
        this.name = name;
        this.gfs = gfs;
    };
    //每一个SonWang构造函数实例化的对象都有一个花钱的方法,那这个方法就可以写在原型中
    SonWang.prototype.flowerMoney = function (  ) {
        console.log ( "我很会花钱哄女孩子吃六块钱的麻辣烫…………" );
    }
    //将wangjianlin对象的所有属性添加到SonWang构造函数的原型中
    // for(var key in wangjianlin){
    //     SonWang.prototype[key] = wangjianlin[key];
    // }
    //调用封装好的继承函数
    extend(SonWang,wangjianlin);

    //实例化对象
    var son1 = new SonWang('聪聪',['雪梨','豆得儿','林更新','王建刚','赵铁柱']);
    console.log ( son1 );
    var son2 = new SonWang('班长',['苍老师','吉泽老师','结衣老师','白石老师']);
    console.log ( son2 );

02-原型链

2.1-原型链介绍

  • 1.原型链:每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链
  • 2.对象访问原型链中的成员规则:就近原则
    • 当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:xxx is not a function
代码语言:javascript
复制
<script>
        //1.构造函数
        function Person(name,age){
            this.name = name;
            this.age = age;
        };

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

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

        //3.实例化对象
        var 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>

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

  • 1.通过查看Array的原型链
    • 了解构造函数的原型本身是一个对象,只要是对象就有原型
  • 2.通过查看Date的原型链
    • 学会举一反三,所有的内置对象(Math Array 基本包装类型等)的原型链都是一样的,最终都指向Object
  • 3.通过查看String的原型链:了解这里的String值得是内置对象String(是一个基本包装类型),其他的Number、Boolean原型链和String是一样的
    • 只有对象才有原型,这里一定要把基本数据类型string、number、boolean,和基本包装类型(特殊的引用类型对象)String、Number、Boolean区分开来,不要搞混淆
代码语言:javascript
复制
/*查看内置对象的原型链*/

    //1.Array
    var 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
    var 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
    var str = new String('123');
    console.log ( str.__proto__ === String.prototype );//true
    console.log ( str.__proto__.__proto__.constructor );//Object
    console.log ( str.__proto__.__proto__ === Object.prototype );//true

    //4.Number
    var num = new Number(666);
    console.log(num.__proto__.constructor);//Number
    console.log(Number.prototype);
    console.log(num.__proto__ === Number.prototype);//true

    //4.界面元素
    var div1 = document.getElementById('div1');
    var p1 = document.getElementById('p1');
    console.log(p1.__proto__);//HTMLParagraphElement
    console.log(div1.__proto__);//HTMLDivElement
    console.log(div1.__proto__.__proto__);//HTMLElement
    console.log(div1.__proto__.__proto__.__proto__);//Element
    console.log(div1.__proto__.__proto__.__proto__.__proto__);//Node
    console.log(div1.__proto__.__proto__.__proto__.__proto__.__proto__);//EventTarget
    console.log(div1.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__);//Object
    console.log(div1.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__);//null

1.3-函数也是对象

  • 1.function函数属于对象类型
    • 如何验证呢?
      • 对象特征:点语法动态赋值
  • 2.既然函数是对象,那它是由哪一个构造函数来创建的呢?
    • Function构造函数
  • 3.既然函数是对象,那么构造函数Function本身也是对象,它又是由谁构造生成的呢?
    • Object构造函数
代码语言:javascript
复制
 <script>
        /* 
        函数 : 属于对象类型。
            如何验证 :对象可以点语法动态赋值,如果函数也可以像对象一样使用点语法取值赋值,
            就可以证明函数也是对象
         */

        function fn(){
            //存储代码
            console.log('1111');
        };

        fn.aaa = '啊啊啊';
        fn.eat = function(){
            console.log('我中午请你吃饭');
        };
        fn.eat();

        console.log(fn); // log:只能打印函数中存储的代码
        console.dir(fn); // dir:打印函数对象内存

        //查看 函数对象 的原型链
        console.log(fn.__proto__.constructor);//Function
        console.log(fn.__proto__ === Function.prototype);//true

        //查看 函数对象 原型的原型
        console.log(fn.__proto__.__proto__.constructor);//Object
        console.log(fn.__proto__.__proto__ === Object.prototype);//true
        
    </script>

1.4-Function构造函数

  • 1.函数属于对象类型,它是由Function()构造函数生成
    • js中的函数都是由Function()构造函数实例化的对象,包括Object构造函数
  • 2.介绍Function构造函数的语法
代码语言:javascript
复制
<script>
        /* 
        1.js中所有的函数对象 , 都是被 Function构造函数创建
        */

        //1. new Function()
        //参数 (1)前面所有的参数都是函数形参  (2)最后一个参数是函数体代码
        //返回值 : 函数对象
        var fn =  new Function('a','b','console.log("6666");return a+b;');
        var res =  fn(10,20);
        console.log(res);
        

        //2.js基础函数两种声明方式
        //这两种声明方式底层都是调用构造函数 new Function()
        //2.1 函数式声明
        function fn1(a,b){
            return a+b;
            
        };

        //2.2 表达式声明
        var fn2 = function(){

        };
    </script>

1.5-完整原型链

  • 1.完整原型链:了解实例化对象,构造函数,原型对象三者之间的关系
  • 2.完整原型链的总结(不考虑个别特殊情况)
    • 对象与构造函数关系(js中的对象都是构造函数生成)
      • a.原型对象由Object构造函数生成
      • b.函数对象由Function构造函数生成
      • c.实例对象由对应的构造函数生成
    • 原型与构造函数关系
      • a.只要是构造函数就有prototype属性指向自身的原型对象
      • b.只要是原型对象就有constructor属性指向对应的构造函数
      • c.只要是对象就有proto指向与之对应的构造函数的原型对象
        • 特殊情况:Object.prototype的原型对象是null
      • d.函数本身也是对象
代码语言:javascript
复制
<script>
        /* 
        完整原型链 : 了解 函数对象 , 原型对象 , 实例化对象三者的关系
            1. js中所有的对象都是被构造函数生成
            2. 不同的对象被不同的构造函数生成
                a. 原型对象由Object构造函数生成
                b. 函数对象由Function构造函数生成
                c. 实例对象由对应的构造函数生成
         */
        //js中有两种构造函数 :

        //1.js作者写好的 : 内置构造函数
        var obj = {};//new Object
        //查看obj的原型
        console.log(obj.__proto__.constructor);//Object
        console.log(obj.__proto__ === Object.prototype);//true
        
        //2.程序员自己写的构造函数:自定义构造函数
        //自定义构造函数
        function Person(name,age){
            this.name = name;
            this.age = age;
        };

        //原型对象
        console.log(Person.prototype);
        //实例化对象
        var p1 =  new Person('小帅',18);

        //函数也是对象 : 函数对象都是被Function构造函数创建
        //1.查看person构造函数对象的原型链
        console.log(Person.__proto__.constructor);//Function
        console.log(Person.__proto__ === Function.prototype);//true
        
        //2.查看Object构造函数原型链
        console.log(Object.__proto__.constructor);//Function
        console.log(Object.__proto__ === Function.prototype);//true
        
        //3.查看Function构造函数的原型链
        console.log(Function.__proto__.constructor);//Function
        console.log(Function.__proto__ === Function.prototype);//true
    </script>

1.6-instanceof运算符原理

  • instanceof语法: 对象 instanceof 构造函数
  • 作用:检测 一个构造函数的原型(prototype) 在不在 一个对象的原型链中(其意思就是判断对象是否是某一数据类型(如Array)的实例,请重点关注一下是判断一个对象是否是数据类型的实例)
代码语言:javascript
复制
	//1.示例
    var 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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01-面向对象三大特征(封装、继承、多态)
    • 1.1-多态(js中了解即可)
      • 1.2-继承(三种实现方式)
        • 1.3-混合式继承函数封装
        • 02-原型链
          • 2.1-原型链介绍
            • 1.2-原型链详解:内置对象的原型链
              • 1.3-函数也是对象
                • 1.4-Function构造函数
                  • 1.5-完整原型链
                    • 1.6-instanceof运算符原理
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档