zoukankan      html  css  js  c++  java
  • 前端面试知识点整理(二)

    (三)DOM事件

    • DOM事件的级别
    • DOM事件模型(捕获,冒泡)
    • DOM事件流
    • 描述DOM事件捕获的具体流程
    • Event 对象的常见应用
    • 自定义事件

     

    DOM事件级别

    事件流

    浏览器在当前页面与目标交互的过程中,动作是怎么传递的如何相应。

    捕获阶段 —— 目标阶段 —— 冒泡阶段

    具体流程

    捕获:window -> document -> html -> body -> ... -> 目标元素

    冒泡反之

    用JS 获取body: document.body

    用JS获取html: document.documentElement

    Event 对象

    event.preventDefault()  阻止默认行为

    event.stopPropagation()  阻止冒泡行为

    event.stopImmediatePrppagation()  事件相应优先级。给目标注册两个事件,执行一个阻止另一个

    event.currentTarget  区分当前哪个元素被点击

    event.target  返回事件的目标节点

    自定义事件

    var eve = new Event('custome');
    ev.addEventListener('custome', function(){
        console.log('custome');
    });
    ev.dispatchEvent(eve);
    捕获事件流程
     
    <div id="ev">
        <style>
            #ev{
                width: 300px;
                height: 100px;
                background-color: red;
                color: #fff;
                text-align: center;
                line-height: 100px;
            }
        </style>
        目标元素
    </div>
    
    <script>
        var ev = document.getElementById('ev');
    
        // 捕获事件流程
        // 第三个参数为true时,事件句柄在捕获阶段执行
        // 把true改为false,就是冒泡阶段流程
    
        window.addEventListener('click',function(){
            console.log('window capture');
        },true);
    
        document.addEventListener('click',function(){
            console.log('document capture');
        },true)
    
        document.documentElement.addEventListener('click',function(){
            console.log('html capture');
        },true);
    
        document.body.addEventListener('click',function(){
            console.log('body capture');
        },true);
    
        ev.addEventListener('click',function(){
            console.log('ev capture');
        },true)
    </script>

    Event 自定义事件

    // 自定义事件 'test'
    var eve = new Event('test');
    
    //注意,参数要和事件名一致
    ev.addEventListener('test',function(){
        console.log('test dispatch');
    })
    
    // 事件派发,直接触发了 ev 上的事件
    //ev.dispatchEvent(eve);
    
    setTimeout(function(){
        ev.dispatchEvent(eve);
    }, 2000);

    CustomEvent 自定义事件

    //创建自定义事件对象,并传入数据
    const ev = new CustomEvent('msg',{
        detail:{
            title: 'this is custom event',
            id :'0010'
        }
    })
    
    //创建该事件行为
    document.body.addEventListener('msg',function(args){
        console.log(args.detail)
    })
    
    //最后绑定新事件对象
    document.body.dispatchEvent(ev);

    (四)HTTP协议类

    • HTTP协议主要特点
    • HTTP报文的组成部分
    • HTTP方法
    • POST GET 区别
    • HTTP状态码
    • 持久连接
    • 管线化

    主要特点:

    简单快速:每个资源是固定的,在协议中处理很简单的,只要输入URI

    灵活:通过一个HTTP协议就可以完成不同数据类型的传输。

    无连接:连接一次就断开不会保持连接

    无状态:客户端再次请求,服务端是无法区分和上一次是否为同一身份

    HTTP报文:

    HTTP方法

    GET - 获取资源

    POST - 传输资源

    PUT - 更新资源

    DELETE - 删除资源

    HEAD - 获得报文首部

     

    HTTP 状态码

     

    持久连接 keep-alive

    HTTP 支持持久连接 (1.1版本)

    HTTP协议采用请求-应答模式,每个请求/应答客户和服务器都要新建一个连接,完成后立即断开。

    使用Keep-alive模式时,keep-alive功能避免了建立或者重新连接。

    管线化 

    类似于将请求和响应打包起来

     五、原型链

    • 创建对象有几种方法
    • 原型、构造函数、实例、原型链
    • instanceof 的原理
    • new 运算符

    创建对象

    //1
    var o1 = {name:'o1'}
    var o2 = new Object({name: 'o2'})
    //2
    var M = function(name){this.name = name}
    var o3 = new M('o3')
    //3
    var p = {name:'p'}
    var o4 = Object.create(p)

    实例:上例中的o1, o11, o2, 只要是对象,它就是一个实例。

    构造函数 : new 后面操作的函数就是构造函数。

     

    构造函数是可以使用 new 运算符来生成一个实例,构造函数也是函数,函数都有一个prototype属性,prototype会初始化一个空对象,就是原型对象。原型对象都有一个构造器,构造器指向声明的那个构造函数。

    构造函数 与 原型对象的关系:

     

    实例 与 原型对象 的关系:

     原型链:

    从一个实例对象往上找构造 这个实例相关联的对象,再往上找又有创造它的上一级原型对象,以此类推一直到Object.prototype 原型对象终止。

    M.prototype.say = function(){
        console.log('say hi')
    }
    var o5 = new M('o5')

    就是说,通过原型链找到原型上的方法,这个方法是被实例所共有的。

    在访问一个实例的时候,在这个实例本身没有找到方法属性,它一直往原型对象上找(通过 __proto__ )。

    函数才有 prototype,实例对象才有 __proto__ ,而函数(也是一个对象)的 __proto__ 就是Function构造函数的实例。

     

     instanceof

    instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型

    constructor 是用来判断实例是属于哪个原型的

     

    六、面向对象

    • 类的声明
    • 生成实例
    • 如何实现继承
    • 继承的几种方式
    //类的声明
    function Animal() {
        this.name = 'name';
    }
    
    //es6中的class声明
    class Animal2{
        constructor(){
            this.name = name;
        }
    }
    
    //实例类的对象
    console.log(new Animal(), new Animal2());

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

    //借助构造函数实现继承
    function Parent1() {
      this.name = "parent1";
    }
    function Child1() {
      //apply call 改变函数运行上下文,把父函数的this挂载到子函数内, 实现子函数继承
      Parent1.call(this);
      this.type = "child1";
    }
    console.log(new Child1());
    /*
    Child1
      name: "parent1"
      type: "child1"
    */

    缺点:Parent1 原型链上的东西并没有被 Child1 继承

    2.借助原型链实现继承
     
    //借助原型链实现继承
    function Parent2() {
      this.name = "parent2";
    }
    function Child2() {
      this.type = "child2";
    }
    //任何一个函数都有Prototype这个属性,作用就是让构造函数的实例能访问到它的原型对象上
    Child2.prototype = new Parent2();
    
    console.log(new Child2());

    缺点:原型对象是共用的,改变一个另一个也会改变

    function Parent2() {
      this.name = "parent2";
      this.play = [1, 2, 3];
    }
    function Child2() {
      this.type = "child2";
    }
    //任何一个函数都有Prototype这个属性,作用就是让构造函数的实例能访问到它的原型对象上
    Child2.prototype = new Parent2();
    
    console.log(new Child2());
    
    var s1 = new Child2();
    var s2 = new Child2();
    console.log(s1.play, s2.play);
    s1.play.push(4);

     

     3.组合方式实现继承

    function Parent3() {
      this.name = "parent3";
      this.play = [1, 2, 3];
    }
    function Child3() {
      Parent3.call(this);
      this.type = "child3";
    }
    Child3.prototype = new Parent3();
    var s3 = new Child3();
    var s4 = new Child3();
    
    s3.play.push(4);
    console.log(s3.play);
    console.log(s4.play);

     

    缺点:Parent3() 执行了两次

     优化方案1:

    function Parent4() {
      this.name = "parent4";
      this.play = [1, 2, 3];
    }
    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);
    console.log(s6.play);

     缺点:原型全指向了Parent4

    优化方案2(完美写法):

    function Parent5() {
      this.name = "parent5";
      this.play = [1, 2, 3];
    }
    function Child5() {
      Parent5.call(this);
      this.type = "child5";
    }
    // 继承父级的原型
    Child5.prototype = Object.create(Parent5.prototype);
    Child5.prototype.constructor = Child5;
    var s7 = new Child5();
    console.log(s7 instanceof Child5, s7 instanceof Parent5);
    console.log(s7.constructor);

  • 相关阅读:
    从IRP说起(转)
    IoSkipCurrentIrpStackLocation .(转)
    IO_REMOVE_LOCK使用方法小结(转载加改正)
    TCP释放连接时为什么time_wait状态必须等待2MSL时间
    网络编程之select
    Ubuntu18.04 安装Chrome浏览器
    Ubuntu修改系统时间
    Linux常用命令总结
    struct ifconf和struct ifreq,获取网线插入状态
    一个简单的客户单与服务端程序
  • 原文地址:https://www.cnblogs.com/anqwjoe/p/10437658.html
Copyright © 2011-2022 走看看