前端,js原型链(一)

HTML

  1. html元素嵌套问题:

    • 元素嵌套:块元素可以包含内联元素或某些块元素,但内联元素却不能包含块级元素,只能包含其他的内联元素。
    • P元素嵌套问题
      <p>
            <div></div>
      </p>
      
      实际结果:
      通过查询,发现原来p元素内无法包裹块级元素。因为我们使用的DTD规定了块级元素是不能放在

      里面的。

    • 内联元素:其实再内联元素中,还是可以区分一下的,有几个元素<img><input>比较特别,它们可以定义宽高。虽然在IE浏览器里,所有元素都可以定义宽高,但是IE自己的标准,并非所有浏览器都支持。W3C称他们为replaced元素,其实就是行内块,虽然这些元素属于Inline,但却具体有一定的block(可以设置宽高),因此我们可以赋予任何元素css属性display:inline-block。本身具有inline-block的元素应该没有
  2. html的行级标签和块级标签

    • 块级标签(独占一行,不和其他元素同一行)
      • 常见块级标签:form、div、p、ul、li、h1~h6、dl、dd
    • 行级标签(和其他元素同一行,不能设置宽高)
      • 常见块级标签:a、span、strong、u、em
  3. HTML语义化

    • 理解:用正确的标签做正确的事
    • 例如:段落用p标签,标题用h系列标签,边栏用aside标签,主要内容用main标签
    • 为什么要关注语义化:
      • 便于团队的开发与维护
      • 在没有加载CSS的情况下也能呈现较好的内容结构与代码结构,易于阅读。
      • 有利于SEO,利于搜索引擎的爬虫依赖来确定上下文的各关键字的权重

CSS

  1. 子元素浮动,如何消除父元素坍塌情况
    1. 在父元素设置overflow:hidden
    2. 为父元素设置高度撑开(height)
    3. 在浮动元素中最后一个兄弟元素设置clear:both(需块级元素)

JS

  1. 继承,封装
    • js继承共分为5种:构造函数式继承、原型链链式继承、组合式继承、寄生式继承和寄生组合式继承
      • 构造函数式继承

        function Flower() //构造函数
        { this.colors = ['黄色', '红色']; 
              this.print = function () { 
                    console.log(this.colors) } 
        }
        function Rose() { 
              Flower.call(this); 
        } ​ 
        var r1 = new Rose(); 
        var r2 = new Rose(); ​ 
        console.log(r1.print()); // [ '黄色', '红色' ] 
        console.log(r2.print()); // [ '黄色', '红色' ] 
        

        我们现在有一个基类Flower,它有一个属性colors,现在我们把某一个实例的colors值改一下:

        r1.colors.push('紫色'); ​ 
        onsole.log(r1.print()); // [ '黄色', '红色', '紫色' ] 
        console.log(r2.print()); // [ '黄色', '红色' ] 
        

        结果如上,显然,改变的只有r1的值,因为通过构造函数创造出来的实例对象中,所有的属性和方法都是实例内部独立的,并不会跟其他实例共享。

        • 总结一下构造函数的优缺点:
          • 优点:所有的基本属性独立,不会被其他实例所影响;
          • 缺点:所有希望共享的方法和属性也独立了,没有办法通过修改父类某一处来达到所有子实例同时更新的效果;同时,每次创建子类都会调用父类构造函数一次,所以每个子实例都拷贝了一份父类函数的内容,如果父类很大的话会影响性能;
      • 原型链链式继承

        function Parent() {//列子
              this.color = 'red';
              this.print = function() { 
              console.log(this.color); 
              } 
        } 
        function Son() { } 
        

        我们有一个父类和一个空的子类;

        Son.prototype = new Parent();
        Son.prototype.constructor = Son; 
        

        接着我们把子函数的原型属性赋值给了父函数的实例;

        var son1 = new Son(); 
        son1.print(); // red 
        

        最后新建子类实例,调用父类的方法,成功拿到父类的color和print属性方法;

        我们重点来分析一下下面两行代码:

        Son.prototype = new Parent(); 
        Son.prototype.constructor = Son; 
        

        这段代码中,子函数的原型赋给了父函数的实例,我们知道prototype是函数中的一个属性,js的一个特性就是:如果一个对象某个属性找不到,会沿着它的原型往上去寻找,直到原型链的最后才会停止寻找。
        我们看到最后实例son成功调用了Print方法,输出了color属性,这是因为son从函数Son的prototype属性上面去找到的,也就是从new Parent这个对象里面找到的;这种方式也不是真正的继承,因为所有的子实例的属性和方法,都在父类同一个实例上了,所以一旦某一个子实例修改了其中的方法,其他所有的子实例都会被影响,来看下代码:

        function Flower() { 
              this.colors = ['黄色', '红色']; 
              this.print = function () { 
                    console.log(this.colors) 
              } 
        } ​ 
        function Rose() {} 
        Rose.prototype = new Flower(); 
        Rose.prototype.constructor = Rose;     
        var r1 = new Rose(); 
        var r2 = new Rose(); ​  
        console.log(r1.print()); // [ '黄色', '红色' ] 
        console.log(r1.print()); // [ '黄色', '红色' ] ​         
        r1.colors.push('紫色'); ​ 
        console.log(r1.print()); // [ '黄色', '红色', '紫色' ] 
        console.log(r2.print()); // [ '黄色', '红色', '紫色' ] 
        

        还是刚才的例子,这次Rose子类选择了原型链继承,所以,子实例r1修改了colors之后,r2实例的colors也被改动了,这就是原型链继承不好的地方。

        • 总结下原型链继承的优缺点
          • 优点:很好的实现了方法的共享;
          • 缺点:正是因为什么都共享了,所以导致一切的属性都是共享的,只要某一个实例进行修改,那么所有的属性都会变化;
posted @ 2020-06-30 18:39  奋斗的小树酱tao  阅读(145)  评论(0编辑  收藏  举报