前端面经总结

1,什么是事件委托,有什么优缺点?

 事件委托又称为事件代理,是利用事件冒泡的原理把其事件处理程序交给父元素来执行。

  优点:

   1,首先是减少了内存占用,性能更好。

   2,加快了整个页面交互的等待时间。

   3,动态添加的节点也可以自动绑上其事件,无需再次绑定事件。

   4,document很快就可以访问,而且可以在页面生命周期的任何时点添加事件处理程序,而不用等待其他事件完成如DOMContentLoaded、load事件。

 缺点:

 1,如果把所有的事件都绑上事件委托,可以会出现事件误判,就是一些不该绑定事件的元素都绑上事件了。

 2,事件委托基于冒泡,对不冒泡的事件不支持。

2,事件委托如何工作:

  如果有个ul,里面有什么li,我们可以在父级元素ul上绑定事件来进行事件委托。

   我们现在的疑问是:ul元素如何知道li元素点击了呢?

   很简单,由于所有li元素都是ul元素的子节点,故他们的事件会冒泡,无论点击哪个li元素,实际上都相当于点击了ul元素。

  现在产生了另一个问题:ul元素如何知道是在哪个li元素上点击的呢?

 我们很容易想到,在ul的事件处理程序中检测事件对象的target属性,就可以得到真正点击的目标元素。

下面我写了一个获取点击的li 的下标和背景色的方法

    <ul id="ul1">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
window.onload = function (){
     var myul = document.getElementById("ul1");
     var myli = myul.getElementsByTagName("li");
     myul.onclick = function(ev){
         var ev = ev || window.event;
         var target = ev.target ||ev.srcElement;
        
         //只让点击li的时候执行 ,点击ul的时候不执行
	       	  while(target.tagName !== 'LI'){
		       	  	//如果点击的元素为ul,直接跳出循环
				    if(target === myul){
                         target = null;
				         break;
				      //否则,将当前元素父元素赋给target
				    }else{
				    	target = target.parentNode;
				    }
                    
	       	  }
          //只让点击的某个li的背景颜色设为红色
          target.style.background = "red";
        
         //获取点击的某个li的下标
          var index;
          for(var i=0;i<myli.length;i++){
              if(myli[i] === target){
                  index=i;
              }
          }
          if(index>=0){alert('我的下标是第'+index+'个')};
     }
}

3,说到事件冒泡,什么是事件冒泡,怎么阻止事件冒泡呢?

当事件发生后,这个事件就要开始传播(从里到外或者从外向里)。因为事件源本身(可能)并没有处理事件的能力,即处理事件的函数(方法)并未绑定在该事件源上。事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中,或者按钮的父级绑定有事件函数,当该点击事件发生在按钮上,按钮本身并无处理事件函数,则传播到父级去处理。这就是事件冒泡。

阻止事件冒泡的方法:

  (1)    w3c的方法是e.stopPropagation()阻止向父级传播 或e.stopImmediatePropagation()包括自身和父级传播,

                IE则是使用e.cancelBubble = true

function stopBubble(e) { 
//如果提供了事件对象,则这是一个非IE浏览器 
if ( e && e.stopPropagation ) 
    //因此它支持W3C的stopPropagation()方法 
    e.stopPropagation(); 
else 
    //否则,我们需要使用IE的方式来取消事件冒泡 
    window.event.cancelBubble = true; 
}

 (2)return false

      javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。

   阻止默认行为的方法:

     w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;

//阻止浏览器的默认行为 
function stopDefault( e ) { 
    //阻止默认浏览器动作(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函数器默认动作的方式 
    else 
        window.event.returnValue = false; 
    return false; 
}

4,js常用的数据类型

    基本的数据类型:

    String,Number ,Boolean, Undefined,Null ,symbol

   引用数据类型:Function  ,Object 

5,基本数据类型和引用数据类型的区别

    (1)内存分配位置不同

         基本数据类型存储在栈中,引用类型在栈中只存放了对象的地址,在堆中存放的是对象的值。

    (2)变量访问的时候不同

       基本数据类型可以直接访问到,

      引用的数据类型不能直接访问,得得到堆内存中的地址,然后用这个地址获取对象中的值,就是按引用访问。

 (3)复制变量的时候不同

     基本数据类型复制时会把值赋值给新变量,这两个变量是完全独立的,只是拥有相同的值。

   引用数据类型复制时只会把内存地址复制给新变量,也就是两个指针指向同一个对象。

6,堆和栈的区别:

     (1) 堆和栈的空间分配区别

          栈是由操作系统自动分配释放,

          堆一般是由程序员分配释放,若程序员不释放,可能会有os回收。

      (2)存放值的不同

           栈一般存放函数的参数值,局部变量的值。

           堆中一般存放对象的值。

      (3)数据结构的区别

            栈的数据结构可以看做先进后出的栈。

            堆可以看做是一颗树。

       (4)缓存方式的区别

            1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;
       2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定。

        (5)调用速度的区别

             栈中的数据调用要比堆中的快。

7,怎么获取变量的数据类型

     (1)常用的typeof(×××) 或 typeof ×××

              判断string,number,boolean,undefined,function 类型的变量可以用typeof来判断

    (2)Object.prototype.toString.call(×××)

             可以判断任何类型, 返回结果是[Object  类型]

     (3)instanceof  返回值为boolean 类型

                  得需要和new 出来类型变量做比较,例如 var a = new String("hello ")  a instanceof String  ------- true 

                 null 和undefined 类型会报错。 

        (4) constructor属性

                 JavaScript内置对象一般都具备constructor属性

                var a = new String("hello ")   可以用 a.constructor.name 来获取类型。

                  null 和undefind 不能获取数据类型。

  8,怎样判断null 数据类型  ,NaN 类型,undefined类型,数组类型

       (1)  判断是否是null类型

              1,===

                  例:var d = null;   console.log(d === null);  -----true

              2,   Object.prototype.toString.call(null)==='[object Null]

                 例:Object.prototype.toString.call(d)==='[object Null]  ----true

     (2)  判断是否是NaN类型

               1,!== Object

                例:var ex= NaN;  console.log(ex !== Object)   -----true

       (3) 判断是否是undefined 类型

            1,=== void 0  或 === undefined

             例:var e = undefined; console.log(e === void 0)  ----- true console.log(e === undefined)  ----- true

            2,typeof ()

             例:var e = undefined; console.log("e:"+typeof(e))

//判断是否是Null
function isNull(obj){
    return obj === null;
}

//判断是否是NaN
function isNaN(obj){
    return obj !== obj;
}

//判断是否是undefined
function isUndefined(obj){
    return obj === void 0;
}

   9、null 和 undefined  的区别

   相同点:

             在 if判断语句中,值都默认为 false

             大体上两者都是代表,具体看差异

 不同点:

  • null转为数字类型值为0,而undefined转为数字类型为 NaN(Not a Number)
  • undefined是在var 声明变量但未对其初始化时(未被赋值时),这个变量就是undefined
  • null值表示空对象指针。就是访问尚未存在的对象时所返回的值。最为常见的一个用法就是作为参数传入(说明该参数不是对象)

  • 设置为null的变量或者对象会被内存收集器回收

10、== 和 ===  的区别

        == 用于一般比较,先检查两个操作数的数据类型,如果相同则进行=== 比较,如果不同则会转化成同一类型后的值看‘值’是否相等

        === 用于严格比较,如果类型不同,其结果就是不等,不需要做类型转换

11、css那些样式可以被子元素继承

        可继承的:font-size,font-weight,line-height,color,cursor

        不可继承的一般是会改变盒子模型的:display,marginborderpaddingheight

12,关于js 中this 指向的理解

13,怎么解决跨域问题,有哪些方法?

我一般用这三种,cors,nginx反向代理,jsonp

  • jsonp : 单纯的 get 一些数据,局限性很大...就是利用script标签的src属性来实现跨域。
  • nginx 反向代理: 主要就是用了nginx.conf内的proxy_pass http://xxx.xxx.xxx,会把所有请求代理到那个域名,有利也有弊吧..
  • cors的话,可控性较强,需要前后端都设置,兼容性 IE10+ ,比如
    • Access-Control-Allow-Origin: http://foo.example // 子域乃至整个域名或所有域名是否允许访问
    • Access-Control-Allow-Methods: POST, GET, OPTIONS // 允许那些行为方法
    • Access-Control-Allow-Headers: X-PINGOTHER, Content-Type // 允许的头部字段
    • Access-Control-Max-Age: 86400 // 有效期

Q: 对于想携带一些鉴权信息跨域如何走起?比如cookie!

需要配置下 header Access-Control-Allow-Credentials:true ,具体用法看下面的nginxdemo

当然cros的配置不仅仅这些,还有其他一些,具体引擎吧....

若是我们要用 nginx或者 express 配置cors应该怎么搞起? 来个简易版本的

  • nginx
location / {
   # 检查域名后缀
    add_header Access-Control-Allow-Origin xx.xx.com;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
    add_header Access-Control-Allow-Credentials true;
    add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;
    add_header Access-Control-Max-Age 86400;
} 

复制代码
  • express, 当然这货也有一些别人封装好的 cors中间件,操作性更强...
let express = require('express');  
let app = express();  

//设置所有请求的头部
app.all('*', (req, res, next) =>  {  
    res.header("Access-Control-Allow-Origin", "xx.xx.com");  
    res.header("Access-Control-Allow-Headers", "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type");  
    res.header("Access-Control-Allow-Credentials","true")
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    next();  
});  

复制代码

有些还会跟你死磕,,除了这些还有其他姿势么...我说了一个HTML5的postMessage....

..因为真心没用过,只是以前查阅的时候了解了下..只能大体点下

这货用于iframe 传递消息居多, 大体有这么两步步

  • window打开一个实例,传递一个消息到一个x域名
  • x 域名下监听message事件,获取传递的消息

这货的兼容性没那么好,而且没考虑周全下容易遭受 CSRF 攻击


 

猜你喜欢

转载自blog.csdn.net/qq_41055607/article/details/85272904