前端面试准备--6.面向对象

面向对象

1、类与实例

    1.1.类的声明
    eg:
       1. function Animal(){
            this.name = "name";
        }
        
       2.ES6中类(class)的声明
        class Animal2{
            constructor(){
                this.name = name;
            }
           
        }
    
    1.2.(如何通过类实例化生成对象)生成实例
    
    eg:
    //如果构造函数后面没有参数,new后面这个()是可以不要的;
    1.console.log(new Animal(),new Animal2());

2、类与继承

    2.1.如何实现继承?
    2.2.继承的几种方式、各个形式都有什么优点和缺点?
    
    继承的本质(原理)就是原型链。

1.借助构造函数实现继承

        (只实现了部分继承,如果父类的属性都在构造函数上,那没有问题;
        如果父类的原型对象上还有方法,子类是拿不到这些方法的)
        
        function Parent1(){
            this.name = "parent1";
        }
        
        function Child(){
            //call和apply改变的是函数运行上下文,把父级(Parent1这个构造函数)在子函数里执行的话,
            同时修改了父级构造函数this的指向,从而导致了父类执行的时候属性都会挂在Child类实例上去。
           
           //将父级的构造函数的this指向一个子构造函数的实例上去,父级构造函数所有的属性在子类中也有
            Parent1.call(this);
            this.type="child1";
        }
        
        console.log(new Child());
        
        缺点:Parent1原型链上的东西并没有被Child所继承;
        没有继承父类原型对象上的方法,导致的并没有真正的实现继承;
        function Parent1(){
            this.name ="Parent1";
        }
        
        Perent1.prototype.say=function(){};
        
        function Child1(){
            Parent1.call(this);
            this.type="child1";
        }
        
        console.log(new Child1(),new Child1().say());//say()不是一个function

2.借助原型链实现继承(弥补构造函数实现继承不足)

        function Parent2(){
            this.name ="parent2";
        }
        
        function Child2(){
            this.type="child2";
        }
        
        //prototype作用为了让这个构造函数(Child2)的实例能访问到原型对象上
        Child2.prototype = new Parent2();
        
        console.log(new Child2()); //Child2{type:"child2",__proto__:Parent2}
        console.log(new Child2().__proto__);//.__proto__===Child2.prototype
        new Child2.__proto__.name;--->"Parent2"
        
        缺点:
         function Parent2(){
            this.name ="parent2";
            this.play=[1,2,3];
        }
        
        function Child2(){
            this.type="child2";
        }
        
        Child2.prototype = new Parent2();
        console.log(new Child2());
        
        var s1= new Child2();
        var s2= new Child2();
        
        console.log(s1.play,s2.play);//[1,2,3];[1,2,3]
        
        s1.play.push(4);
        console.log(s1.play,s2.play);//[1,2,3,4];[1,2,3,4]
        
        在一个类上实例了两个对象,改第一个对象的属性,第二个对象也跟着改变;
        引起这个问题的原因:原型链上的原型对象是共用的;
        s1.__proto__===s2.__proto__;//true

3.组合方式(实现继承的通用方式)

        function Parent3(){
            this.name ="Parent3";
        }
        
        function Child3(){
            Parent3.call(this);//原型链上执行了1次
            this.type="child3";
        }
        
        //父类的构造函数执行了2次
        Child3.prototype = new Parent3(); //new的时候执行了一次
        
        var s3 = new Child3();
        var s4 = new Child3();
        s3.play.push(4);
        console.log(s3.play,s4.play);
        
        console.log(s3.constructor);//Parent3
         ----因为prototype直接拿的父类的实例,它没有自己的constructor,它的constructor是从这个
         实例中继承的,也就是原型链上一级拿过来的,它拿过来的肯定是Parent3的constructor;
       
        缺点:父类的构造函数执行了2次

4.(组合继承的优化)

        //构造函数体内通过两个构造函数的组合能拿到所有构造函数体内的属性和方法
        function Parent4(){
            this.name ="Parent4";
        }
        
        function Child4(){
            Parent4.call(this);//父类只执行了一次
            this.type="child4";
        }
        
        //对象引用类型(优点:原型对象是只是一个简单的引用,不会执行父级的构造函数)
        Child4.prototype = Parent4.prototype;
        
        var s5 = new Child4();
        var s6 = new Child4();
        s5.play.push(4);
        
        console.log(s5.play,s6.play);
        
        
        //判断这个对象是不是这个类的实例
        console.log(s5 instanceof Child4,s5 instanceof Parent4);//true,true
   
    问题:怎么区分一个对象是直接由它的子类实例化的,还是它的父类实例化的?
    (怎么区分s5是是Child4的实例还是Parent4直接实例化的?)
    
    
        //指向了父类Parent4{this.name="parent4";this.play=[1,2,3]}
        console.log(s5.constructor); 
        
        ---prototype里面有一个属性constructor,而我们的子类原型对象和父类的原型对象是一个对象,这个对象的constructor
        就是父类里的constructor,这个父类的constructor指的是Parent4自己;
      
       ----因为prototype直接拿的父类的实例,它没有自己的constructor,它的constructor是从这个
         实例中继承的,也就是原型链上一级拿过来的,它拿过来的肯定是Parent4的constructor;

5.组合继承优化2(完美版)

    function Parent5(){
        this.name ="name";
        this.play=[1,2,3];
    }
    
    function Child5(){
        Parent5.call(this);
        this.type="Child5";
    }
    
    
    //Object.create创建对象的原理:
    //--- Child4.prototype = Parent4.prototype;引用同一个对象,说白是一个对象,缺点:它俩的构造函数指向的是一个
    (constructor是一个)无法区分实例是由父类创建的还是子类创建的;
    
    //---Object.create(Parent5.prototype);创建中间对象方法,就把两个原型对象区分开,这个中间对象还具备一个特性就是它的原型
    对象是父类的原型对象,这样在原型链上又开始连起来了。
     --通过在给Child5原型对象上的constructor做修改,就能正常区分父类和子类的构造函数了。
   
    Child5.prototype = Object.create(Parent5.prototype);
    Child5.prototype.constructor = Child5;
    
    var s7 = new Child5();
    var s8 = new Child5();
    
    s6.play.push(4);
    
    console.log(s7 instanceof Child5,s7 instanceof Parent5);//true true
    consoel.log(s7.constructor); //Child5
    
    
***为什么通过Object.create方法创建的这个对象就能作为它俩之间的桥梁呢?
    Object.create创建的对象有什么特点?
    --Object.create它创建的这个对象,原型对象就是参数;
    
原理:Child5实例的原型对象等于Child5.prototype,Child5.prototype又等于Object.create方法创建的对象,这个中间对象原型对象又是
(prototype)父类的原型对象,所以一级的上一级的上一级,通过这样找实现了继承;而且还达到了父类和子类原型对象的隔离;
    
对象通过.__proto__ (这个属性往上找它的原型对象的)一级一级往上找;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 本章内容 理解对象属性 理解并创建对象 理解继承 面向对象语言有一个标志,那就是它们都有类的概念,而通过类可以创建...
    闷油瓶小张阅读 834评论 0 1
  • 1.继承(接口继承和实现继承) 继承是 OO 语言中的一个最为人津津乐道的概念。许多 OO 语言都支持两种继承方式...
    believedream阅读 930评论 0 3
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,391评论 3 12
  • 2017年深圳出台了新的人才引进政策后,如果你想办理深圳户口,那么你需要什么条件才能办理呢?如何知道你的条件是否达...
    深圳小老大阅读 357评论 0 0
  • L/2013-8 如果这个世界上真的有轮回,来世你还会希望遇见我吗。 主人 十五岁之前我是很喜欢猫的,十五岁...
    MY林小妖阅读 288评论 3 2