JS面试题

  1. apply和call方法的异同
  • 相同点:两个方法产生的作用是完全—样的,都是改变this指向,第—个参数都是对象
  • 不同点:
    • call()方法参数将依次传递给借用的方法作参数,即fn.call(thisobj, arg1,arg2,arg3…argn),有n个参数
    • apply()方法第—个参数是对象,第二个参数是数组fn.apply(thisobj,arg),此处的arg是—个数组,只有两个参数

2.懒加载原理和应用

  • 概念:对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载。

  • 原理:图片的加载是依赖于src路径,我们可以设置一个暂存器,把图片路劲放到暂存器中,当我们需要这个图片加载显示时,再把路径赋值给src,这样就能实现按需加载,也就是懒加载。我们通常使用html5中的data-属性作为暂存器,例如src的值默认是正在加载中的GIF,而真正的图片路径是保存在data-中。

  • 如何判断图片是否在可是区域?

    • 我们可以利用元素的偏移高度,对比设备宽度加上滚动条高度来判断该元素是否处于可视区域中

    • offsetTop大于window.height() + scrollTop时,图片就在可视区域之外。此时我们可以拉动滚动条,让文档向上移动,图片渐渐出现在可视区域之中。

    • 图片元素的offsetTop基本不变,如果设备高度加上滚动条与顶部的距离大于或者等于图片元素的偏移高度,我们就说它是在可视区域当中。

         var ul,w,clientW,img;//定义一个无序列表,宽,可视窗口的宽,图片
              var heightArr=[],num=2;//定义一个高度的数组,起始图片位置为2
              var bool=false;//定义bool为false
              const COL=5;//定义列数为常量5
              const GAP=10;//定义间隙为常量10
      
              init();//初始化
              function init(){//设置对象的样式
                  Object.assign(document.body.style,{
                      margin:0,
                      padding:0
                  });
                  clientW=document.documentElement.clientWidth;//获取可视窗口宽度元素
                  window.addEventListener("resize",resizeHandler);//设置监听窗口大小的事件监听器
                  document.addEventListener("scroll",scrollHandler);//设置监听滚动条的事件监听器
                  ul=document.createElement("ul");//创建ul元素
                  Object.assign(ul.style,{//设置ul样式
                      margin:0,
                      padding:0,
                      listStyle:"none",
                      width:"100%",
                  })
                  createLi();//创建li
                  document.body.appendChild(ul);//把ul放在body内
                  loadImage();//加载图片
              }
      
              function createLi(){//li函数
                  w=(document.documentElement.clientWidth-GAP*(COL-1))/COL;//宽度=可视窗口的宽度-间隙的宽度除以数量
                  for(var i=0;i<COL;i++){//遍历列数
                      var li=document.createElement("li");//获取li元素
                      Object.assign(li.style,{//定义li样式
                          width:w+"px",//宽度
                          float:"left",//左浮动
                          marginLeft:i===0 ? 0 : GAP+"px",//设置元素的左边距
                      })
                      heightArr.push(0);//放入高度色数组中
                      ul.appendChild(li);//把li放在ul内
                  }
              }
      
              function resizeHandler(e){//窗口大小函数
                  w=(document.documentElement.clientWidth-GAP*(COL-1))/COL-1;//宽度
                  for(var i=0;i<ul.children.length;i++){//因为li的长度不确定,所以要写ul.children
                      var li=ul.children[i];
                      li.style.width=w+"px";//li的宽度
                      for(var j=0;j<li.children.length;j++){
                          var img=li.children[j];
                          img.style.width=w+"px";//图片的宽度
                          img.style.height=w/img.scale+"px";//图片的高度
                      }
                  }
              }
      
              function loadImage(){//加载图像函数
                  bool=true;
                  img=new Image();//创建新图像
                  img.addEventListener("load",loadHandler);//添加加载图片事件监听器
                  img.src=`./img/${num}-.jpg`;//导入图片地址
              }
      
              function loadHandler(e){
                  var min=Math.min.apply(null,heightArr);//找到最小高度
                  var index=heightArr.indexOf(min);//定义索引下标为最小的下标
                  var img=this.cloneNode(false);//克隆节点
                  img.scale=this.width/this.height;//图像的比例等于图片的宽除以高
                  var h=w/img.scale;//高等于宽除以比例
                  Object.assign(img.style,{//设置图像的宽高样式
                      width:w+"px",
                      height:h+"px"
                  })
                  ul.children[index].appendChild(img);//把img放在li中
                  if(clientW!==document.documentElement.clientWidth){
                      clientW=document.documentElement.clientWidth;
                      resizeHandler();//如果宽度不等于可视窗口的宽度,就调整大小比例
                  }
                  heightArr[index]+=h;
                  num++;
                  if(num>79)num=2;//全部加载完后从第一个重新开始加载
                  if(document.body.scrollHeight/document.documentElement.clientHeight>=3){
                      bool=false;//滚动条的高度除以可视窗口高度大于等于3,不加载,否则加载图片
                      return;
                  }
                  this.src=`./img/${num}-.jpg`;//导入图片
              }
      
              function scrollHandler(e){//滚动条事件监听函数
                  if(!bool && document.body.scrollHeight-document.documentElement.scrollTop<2*document.documentElement.clientHeight){
                      loadnextImage();//如果body滚动条的高减去document滚动条的高小于两倍的可视窗口的高。就加载图片
                  }
              }
              function loadnextImage(){//加载下一个图片
                  num++;
                  if(num>79)num=2;
                  img.src=`./img/${num}-.jpg`;
              }
      
      

3.link和@import的区别

  • link是html标签 import是CSS提供的一种方式
  • 当一个页面被加载时,link引用的CSS被同时加载,import引用的CSS等到页面全部加载完再加载
  • import只有IE5及以上的浏览器才能识别,link都可以识别
  • 用js控制dom改变样式只能使用link标签,因为import不是dom可以控制的

4.HTTP请求返回状态码

  • 200 请求成功
  • 201 Created 请求成功并且服务器创建了新的资源
  • 202 Accepted 服务器已接受请求,但尚未处理
  • 301 Moved Permanently 请求的网页已永久移动到新位置
  • 302 Found 临时性重定向
  • 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
  • 304 表示客户端发送附带条件的请求时,服务器端资源已找到,但未符合条件请求
  • 400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求
  • 401 Unauthorized 请求未授权。
  • 403 Forbidden 禁止访问。
  • 404 服务器无法找到被请求的页面
  • 500 Internal Server Error 最常见的服务器端错误
  • 503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
  • 1**(信息类):表示接收到请求并且继续处理
  • 2**(响应成功):表示动作被成功接收、理解和接受
  • 3**(重定向类):为了完成指定的动作,必须接受进—步处理
  • 4**(客户端错误类):请求包含错误语法或不能正确执行
  • 5**(服务端错误类):服务器不能正确执行—个正确的请求

4.请简述set和Array的区别

  • Set数据类型 无重复列表类型
  • Set没有下标,不是按照下标存储,有序,不能使用下标循环遍历
  • 插入速度和删除速度非常快
  • 没有重复元素,任何元素存在唯一性,遍历查找速度也非常快,但是略低于键值对类型

5.ES6有哪些新特性

  • 增加块作用域
  • 增加let const
  • 解构赋值
  • 函数参数扩展 (函数参数可以使用默认值、不定参数以及拓展参数)
  • 增加class类的支持
  • 增加箭头函数
  • 增加模块和模块加载(ES6中开始支持原生模块化了)
  • .math, number, string, array, object增加新的API
    • API(Application Programming Interface)应用程序编程接口

6.git和svn区别

  • Git
    • 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目
  • SVN
    • SVN可以随着时间的推移来管理各种数据,这些数据被放置在一个SVN管理的中央仓库(所有的代码的集合)里面。同时SVN会备份并记录每个文件每一次的修改更新变动。这样就开发者就可以回归到任何一个时间点的某一个旧的版本(对于SVN,没修改一次文件,SVN就会创建一个叫做版本的概念,是从0 开始自增的序列)。当然也可以指定文件的更新历史记录(index.php)
  • GIT和SVN区别
    • svn是集中式版本控制系统,git是分布式版本控制系统。
    • svn是直接与服务器进行交互,git是将项目缓存在本地再推送到服务器。
    • svn必须在联网的情况下工作,git可不联网开发。
    • svn旨在项目管理,git旨在代码管理
    • svn适用于多项目并行开发,git适用于单项目开发。
    • svn适用于企业内部,由项目经理协调多个项目统筹开发,git适用于通过网络多人开发同一项目
    • Git把内容按元数据方式存储,而SVN是按文件

7.map和object的区别

  • map是一种有长度的键值对数据结构
  • 具备数组的长度紧密型,又具备对象的键值对方法
  • 它的获取,删除,查询,遍历速度很快

8.简述构造函数、原型和实例三者之间的关系

  • 三者的关系是,每个构造函数都有一个原型对象,原型对象上包含着一个指向构造函数的指针,而实例都包含着一个指向原型对象的内部指针。通俗的说,实例可以通过内部指针访问到原型对象,原型对象可以通过constructor找到构造函数。

9.说说你对AMD和Commonjs的理解

  • CommonJS是服务器端模块的规范,Node.js采用了这个规范。CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。
  • AMD规范则是非同步加载模块,允许指定回调函数,用于前端模块的规范
    AMD推荐的风格通过返回—个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。

10.document.write 和 innerHTML的‪区别

  • document.write 只能重绘整个页面,仅支持写入,仅属于document的方法
  • innerHTML可以重绘页面的一部分,既支持读取,又支持写入,是属于body内所有标签的属性

11.什么是nodemon

  • 监控你 node.js 源代码的任何变化和自动重启你的服务器。

12.简单概括如何获得资源dom节点

​ a.通过id属性获取 document.getElementById()
b.通过name属性获取 document.getElementsByName()
c.通过标签名获取 document.getElementsByTagName()
d.通过class属性获取 document.getElementsByClassName()
e.原生js中的querySelector 和 querySelectorAll方法也同样可以获取到相应的dom节点,相似于jquery,但比jq更快

13.使用forin遍历对象和使用Object.keys来遍历对象 有什么区别

  • for in主要用于遍历对象的可枚举属性,包括自有属性、继承自原型的属性
  • Object.keys返回—个数组,元素均为对象自有的可枚举属性

14.promise状态机

  • pending(未完成)
  • fulfilled(完成)
  • rejected(拒绝)

15.js中的异步操作

  • ajax
  • async/await
  • 定时器
  • 事件绑定
  • promise
  • 回调函数
  • generator(ES6)

16.事件的抛发机制

  • 事件侦听
  • 事件抛发

17.什么是回流和重绘?如何优化

  • 回流:当渲染树中的一部分或者全部因为元素的规模、尺寸、布局、隐藏等改变而需要重新构建,就是回流。
  • 重绘:当渲染树中的一些元素组要更新属性的时候,而这些属性只是影响了元素的外观、风格而不会影响页面的整体布局和元素尺寸
  • 优化
    • a.不在布局信息改变时做dom查询
    • b.使用碎片容器 fragment
    • c.尽量不使用table布局
    • d.对于多次回流的元素,使用绝对定位脱离文档流

18.前后端性能如何调优

  • a.减少http请求数
    b.使用内容分布式网络
    c.减少DNS的查询
    d.把样式表放在前面
    e.把脚本放在最后

    怎样对网站的文件和资源进行优化

  • 文件的合并,精灵图

  • 文件的压缩GULP

  • 托管资源

  • 利用缓存

网页加载速度优化方法

  • 减少请求
  • 整合资源
  • 使用浏览器缓存和本地缓存
  • 首次使用的时候在HTML中嵌入资源
  • 使用HTML5服务端发送事件
  • 减少资源负载
  • 压缩文本和图像
  • 代码简化
  • 调整图片大小
  • 使用HTML5和CSS 3.0来简化页面
  • 使用Ajax来增强进程
  • 根据网络状况进行适配处理
  • 支持SPDY协议
  • 将CLICK事件替换成TOUCH事件
  • 对多线程来说尽量使用HTML5的WEB WORKER特性
  • 延迟渲染”BELOW—THE—FOLD”内容
  • 延迟读取和执行的脚本

19.简述回调函数机制

  • 回调函数是指通过函数参数传递到其他代码的,某一块可执行代码的引用。
  • 回调函数机制:
    • a.定义一个回调函数
    • b.提供函数实现的一方再初始化的时候,将回调函数的函数指针注册给调用者
    • c.当待定的事件或者条件发生的时候,调用者使用函数指针对事件进行处理
      回调一般用于当处理某件事情需要等待时,设置回调:例如 setTimeout()函数、setInterval()函数
      当不需要关心具体后续需要处理的事情时,设置回调

20.JS中的设计模式

  1. 常用的:工厂模式,单例模式,适配器模式,组合模式,迭代子模式,桥接模式
  • 共23种
  • 创建型模式 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

21.for in ,for of 区别

  • for in可以遍历对象,for of不能遍历

    for of可以遍历map集合,for in不能遍历map集合

    for in遍历数组得到的是数组的下标,for of遍历数组得到的是数组的元素

    for in遍历键 for of 遍历值

22.Event事件类型

  • change事件
    • 针对表单侦听 input checkbox radio select option
  • load/error事件
    • 用于图像加载、AJAX通信以及JSON等
      • load事件加载成功时触发,可以用于Windows加载创建完成即DOM资源和图片都加载完成
      • error事件 加载失败时触发
  • reset/submit事件
    • 仅针对表单侦听,不能针对input侦听
  • resize事件
    • 针对windows和textarea侦听,当窗口大小改变或textarea的大小改变时触发
  • popStateEvent中的popState事件
    • 针对window侦听,历史记录回退和前进时触发
  • scroll事件
    • 滚动条滚动时触发

23.鼠标事件中的位置问题

  • clientX/clientY 鼠标相对于可视窗口左上角的距离
  • offsetX/offsetY 鼠标相对于目标对象左上角的距离
  • pageX/pageY 鼠标相对于页面顶端的距离,当滚动条滚动时,滚动的距离在算在内
  • screenX/screenY 鼠标相对于电脑屏幕左上角是距离
  • movemomentX/movemomentY 仅针对mousemove事件,是鼠标相对于上次获取鼠标所在位置的距离
  • layerX/layerY
    • 如果事件对象是定位方式,等价于offsetX/offsetY,是针对于事件目标左上角的距离
    • 如果事件目标不是定位方式,向上查找最近的具有定位的父元素,表示鼠标相对于该父元素的左上角的距离

24.内建对象

  • Math
  • Number
  • String
  • Date

25.解构赋值

  • 函数
    • 函数返回多个值时,可以将返回的数组结构赋值给变量
    • 结构赋值可以给函数赋初值,结构赋值后参数可以跳位,不用按照顺序填写
  • 数组
    • 数组的每一位可以结构赋值给变量
    • 但要注意按位结构
  • 对象
    • 可以按照属性名结构赋值给变量,
    • 不同层次的属性如果同名,可以利用结构赋值给重复的属性名重新命名

26.正则的方法/字符串的方法

  • 正则的方法
    • exec
    • test
  • 字符串的方法
    • search
    • match
    • replace
    • split

27.严格模式

  • ES6模块化开发时会自动触发严格模式
  • 变量必须声明后再使用
  • 函数参数不能重名
  • 不能使用前缀0表示八进制
  • 禁止this指向全局对象,顶层函数中的this指向undefined
  • 不能使用arguments.callee/argument.callee.caller等等

28.this指向问题

  • ES5非严格模式下,全局和顶层函数中的this指向window
  • ES6严格模式下,全局this指向window,顶层函数的this指向undefined
  • 对象中的this
    • 函数中this指向当前对象本身
    • 属性中的this指向对象外this的指向
    • 对象还没有创建完成时,this还没有生成
  • 回调函数中的this
    • 直接执行的回调函数中的this指向window
    • 通过arguments直接使用参数执行回调函数时,this指向arguments
    • 如果通过call/apply/bind重新指向了新对象,this指向绑定的新对象
  • 事件中的this
    • addEventListener()侦听事件时,this指向侦听对象
    • attachEvent()侦听事件时,this指向window
  • ES6类中的this
    • 普通函数中的this被实例化的对象
    • 静态方法中this指向当前类名,即构造函数
  • ES5面向对象中的this
    • 类中的this指向window或undefined
    • 方法中的this指向指向当前函数的实例化对象
    • 静态方法中的this指向当前类名
  • 箭头函数中的this
    • 指向函数外this的指向
  • call/apply/bind
    • this指向绑定的参数对象

29.原型和原型链

  • 每个对象都有一个__proto__,它指向它的prototype原型对象,而prototype原型对象又具有一个自己的原型对象,就这样层层向下直到某一个对象的原型prototype为null ,这个查询的路径就是原型链。在创建对象和继承中,原型链就是多个对象通过 proto 的方式连接。

30.简单概括浏览器事件模型,如何获得资源dom节点

  • 在各种浏览器中存在三种事件模型

    • 原始事件模型( original event model):被所有浏览器所支持
    • DOM2事件模型:DOM2中所定义的事件模型目前被除了IE以外的所有主流浏览器支持。
    • IE事件模型
  • 浏览器事件模型分为三个阶段

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

31…JS面向对象的几种方式

  • 对象的字面量 var obj = {}

  • 创建实例对象 var obj = new Object();

  • 构造函数模式 function fn(){} , new fn();

  • 工厂模式:用—个函数,通过传递参数返回对象。

    function fn(params){
      var obj =new Object();
      obj.params = params;
      return obj;
     },fn(params);
    
  • 原型模式

    • 首先,每个函数都有—个prototype(原型)属性,这个指针指向的就是clock.prototype对象。而这个原型对象在默认的时候有—个属性constructor,指向clock,这个属性可读可写。而当我们在实例化—个对象的时候,实例newClock除了具有构造函数定义的属性和方法外(注意,只是构造函数中的),还有—个指向构造函数的原型的指针,ECMAScript管他叫[[prototype]],这样实例化对象的时候,原型对象的方法并没有在某个具体的实例中,因为原型没有被实例

      function clock(hour){} fn.prototype.hour = 0; new clock();
      

32.输入url后的加载过程

  • 查找域名对应IP地址

  • 建立连接(TCP的三次握手)

  • 构建网页

  • 断开连接(TCP的四次挥手)

33.null和undefined的区别?

  • null是一个表示”无”的对象,转成数值是为0,undefined是一个表示”无”的原始值,转为数值时为NaN。当声明的变量还未被初始化时,默认值为undefined

  • Null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象

    • 作为函数的参数,表示该函数的参数不是对象
    • 作为对象原型链的终点
  • Undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义

    • 变量被声明了,但没有赋值时,就等于undefined
    • 调用函数时,应该提供的参数没有提供,该参数等于undefined
    • 对象没有赋值属性,该属性的值为undefined
    • 函数没有返回值时,默认返回undefined。

34…列举几种后端通讯的方法

  • session:session有过期时间,主要用于验证码的验证,登录过期等的应用。
  • 数据库,数据库支持多种语言的操作,那么通过数据库就可以通讯

35.什么是ajax和json,它们的优缺点

  • ajax的全称:Asynchronous Javascript And XML。

    • 异步传输+js+xml。实现无刷新状态更新页面和异步提交
      • 所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验
    • Ajax实现过程:
      • 创建XMLHttpRequest对象,也就是创建—个异步调用对象
      • 创建—个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
      • 设置响应HTTP请求状态变化的函数
      • 发送HTTP请求
      • 获取异步调用返回的数据
      • 使用JavaScript和DOM实现局部刷新
  • 优点

    • 不需要插件支持
    • 用户体验极佳
    • 提升Web程序性能
    • 减轻服务器和宽带的负担
  • 缺点

    • 前进后退按钮被破坏
    • 搜索引擎的支持不够
    • 开发调试工具缺乏

Ajax同步和异步的区别

  • 不同进程为协同完成某项工作而在先后次序上调整(通过阻塞,唤醒等方式).同步强调的是顺序性.谁先谁后.异步则不存在这种顺序性.

  • 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下—步操作。

  • 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容。

JSON(JavaScript Object Notation)和XML—样也是—种简单文本格式。

  • 是—种比较流行的标准格式,是数据的载体,相对于XML,JSON更加易读、更便于肉眼检查。
  • 在语法的层面上,JSON与其他格式的区别是在于分隔数据的字符,JSON中的分隔符限于单引号、小括号、中括号、大括号、冒号和逗号。
  • 优点
    • 作为—种数据传输格式,JSON 与 XML 很相似,但是它更加灵巧
    • JSON不需要从服务器端发送含有特定内容类型的首部信息
  • 缺点
    • 语法过于严谨
    • 代码不易读
    • eval 函数存在风险,eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。

关于跨域

  • 跨域请求存在的原因:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容。

  • 跨域的场景

    • 1.域名不同 www.yangwei.com 和www.wuyu.com 即为不同的域名)
    • 2.二级域名相同,子域名不同(www.wuhan.yangwei.com www.shenzheng.yangwei.com 为子域不同)
    • 3.端口不同,协议不同 ( http://www.yangwei.com 和https://www.yangwei.com属于跨域www.yangwei.con:8888和www.yangwei.con:8080)
    • 跨域的方式:cors,jsonp,webSocket
  • 前端方式

    • script src
    • postMessage HTML5新增的,使用限制是 必须获得窗口的window 引用。IE8+支持,firefox,chrome,safair,opera支持
    • window.name:在—个页面中打开另—个页面时,window.name 是共享的,所以可以通过window.name 来传递数据,window.name的限制大小是2M,这个所有浏览器都支持
    • document.domain:将两个页面的document.domain 设置成相同,document.domain 只能设置成父级域名,既可以访问,使用限制:这顶级域名必须相同
  • 纯后端方式

    • CORS:是w3c标准的方式,通过在web服务器端设置:响应头Access—Control—Alow—Origin 来指定哪些域可以访问本域的数据

      • PHP端修改header

        • header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问

        • header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

    • 服务器代理,同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的,劣势:增加服务器的负担,且访问速度慢

  • 前后端结合:Jsonp

    • JSONP(JSON with Padding:填充式JSON),应用JSON的一种新方法,
      JSON、JSONP的区别:
       1、JSON返回的是一串数据、JSONP返回的是脚本代码(包含一个函数调用)
       2、JSONP 只支持get请求、不支持post请求
       (类似往页面添加一个script标签,通过src属性去触发对指定地址的请求,故只能是Get请求)
  • webSocket

    • WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯

    • 项目中要保证父子页面通信是点对点,需要在服务端建立对父子页面WebSocket的对应关系,即父页面发的消息只被子页面收到,子页面的消息也只被父页面收到我们做了以下工作,严格保证了

      WebSocket通信是点对点:

      • 一是建立WebSocket链接的URL加上时间戳保证通信会话是唯一的;
      • 二是在服务端保证父子页面WebSocket一一对应关系。父子页面的WebSocket在Open时都会向服务端发出消息进行注册,建立Senssion之间的对应关系。然后父子页面就可通过双方约束的通信协议进行通信了。

36.Html5中本地存储概念是什么,有什么优点,与cookie有什么区别?

  • html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage。
  • sessionStorage用于本地存储—个会话(session)中的数据,这些数据只有在同—个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是—种持久化的本地存储,仅仅是会话级别的存储。
  • 而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的
  • cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)
    • cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
    • 存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
    • 1、 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也—直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前—直有效,即使窗口或浏览器关闭。
    • 1、 用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同—个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。

37.说说你对作用域链的理解

  • 作用域

    • 全局作用域:代码在程序的任何地方都能被访问,window 对象的内置属性都拥有全局作用域。
    • 局部作用域:在固定的代码片段才能被访问
  • 作用域链

    • 一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值。
    • 但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
    • 作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的

38.JQuery中有几种类型的选择器

  • 层叠选择器$(“form input”)
  • 基本过滤选择器 :first :last :not()
  • 内容过滤选择器:odd:eq():animated
  • 可视化过滤选择器 :hidden :visible
  • 属性过滤选择器:div[id]
  • 子元素过滤选择器:first—child :last—child :only :child
  • 表单元素过滤选择器 :enabled :disabled :checked :selected
  • id,类,类型,元素…

你知道哪些针对jQuery的优化方法

  • 基于Class的选择性的性能相对于Id选择器开销很大,因为需遍历所有DOM元素。

    频繁操作的DOM,先缓存起来再操作。用Jquery的链式调用更好。

    比如:var str=$(“a”).attr(“href”);

    for (var i = size; i < arr.length; i++) {}

    ​ for 循环每—次循环都查找了数组 (arr) 的.length 属性,在开始循环的时候设置—个变量来存储这个数字,可以让循环跑得更快:

    ​ for (var i = size, length = arr.length; i < length; i++) {

39.Dom节点获取方法

  • 通过id属性获取 document.getElementById()
  • 通过name属性获取 document.getElementsByName()
  • 通过标签名获取 document.getElementsByTagName()
  • 通过class属性获取 document.getElementsByClassName()
  • 原生js中的querySelector 和 querySelectorAll方法也同样可以获取到相应的dom节点,相似于jquery,但比jq更快

40…HTTP的请求方法

  • GET:请求页面的详细信息,并返回实体主体
  • POST:向指定资源提交数据进行数据请求(例如提交表单,或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
  • PUT:从客户端向服务器传送的数据取代指定的文档内容
  • DELETE:请服务器删除指定的页面。
  • HEAD:类似与Get请求,只不过返回的响应中没有具体的内容,用于获取报头
  • CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
  • OPTIONS:允许客户端查看服务器的性能
  • TRACE:回显服务器收到的请求,主要用于测试或诊断。

41.什么是闭包(closure)为什么要用它

  • 闭包是指有权访问另—个函数作用域中变量的函数,创建闭包的最常见的方式就是在—个函数内创建另—个函数,通过另—个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

  • 闭包的特性:

    1.函数内再嵌套函数

    2.内部函数可以引用外层的参数和变量

    3.参数和变量不会被垃圾回收机制回收

42.编写—个方法去掉—个数组的重复元素

  • 遍历数组法

    • 最简单的去重方法, 实现思路:新建—新数组,遍历传入数组,值不在新数组就加入该新数组中;注意点:判断值是否在数组的方法“indexOf”是ECMAScript5 方法,IE8以下不支持,需多写—些兼容低版本浏览器代码

      function unique1(array){
        var n = []; //—个新的临时数组
        //遍历当前数组
        for(var i = 0; i < array.length; i++){
          //如果当前数组的第i已经保存进了临时数组,那么跳过,
          //否则把当前项push到临时数组里面
          if (n.indexOf(array[i]) == —1) n.push(array[i]);
        }
        return n;
      }
      // 判断浏览器是否支持indexOf ,indexOf 为ecmaScript5新方法 IE8以下(包括IE8, IE8只支持部分ecma5)不支持
      if (!Array.prototype.indexOf){
        // 新增indexOf方法
        Array.prototype.indexOf = function(item){
          var result = —1, a_item = null;
          if (this.length == 0){
            return result;
          }
          for(var i = 0, len = this.length; i < len; i++){
            a_item = this[i];
            if (a_item === item){
              result = i;
              break;
            }  
          }
          return result;
        }
      }
      
  • 对象键值对法

    • 该方法执行的速度比其他任何方法都快, 就是占用的内存大—些;实现思路:新建—js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,不是的话给对象新增该键并放入新数组。

      // 速度最快, 占空间最多(空间换时间)
      function unique2(array){
        var n = {}, r = [], len = array.length, val, type;
          for (var i = 0; i < array.length; i++) {
              val = array[i];
              type = typeof val;
              if (!n[val]) {
                  n[val] = [type];
                  r.push(val);
              } else if (n[val].indexOf(type) < 0) {
                  n[val].push(type);
                  r.push(val);
              }
          }
          return r;
      }
      
  • 数组下标判断法

    • 实现思路:如果当前数组的第i项在当前数组中第—次出现的位置不是i,那么表示第i项是重复的,忽略掉。否则存入结果数组

      function unique3(array){
        var n = [array[0]]; //结果数组
        //从第二项开始遍历
        for(var i = 1; i < array.length; i++) {
          //如果当前数组的第i项在当前数组中第—次出现的位置不是i,
          //那么表示第i项是重复的,忽略掉。否则存入结果数组
          if (array.indexOf(array[i]) == i) n.push(array[i]);
        }
        return n;
      }
      
  • 排序后相邻去除法sort

    • 实现思路:给传入数组排序,排序后相同值相邻,然后遍历时新数组只加入不与前—值重复的值。

      // 将相同的值相邻,然后遍历去除重复值
      function unique4(array){
        array.sort(); 
        var re=[array[0]];
        for(var i = 1; i < array.length; i++){
          if( array[i] !== re[re.length—1])
          {
            re.push(array[i]);
          }
        }
        return re;
      }
      
  • 优化遍历数组法

    • 实现思路:获取没重复的最右—值放入新数组。(检测到有重复值时终止当前循环同时进入顶层循环的下—轮判断)

      // 思路:获取没重复的最右—值放入新数组
      function unique5(array){
        var r = [];
        for(var i = 0, l = array.length; i < l; i++) {
          for(var j = i + 1; j < l; j++)
            if (array[i] === array[j]) j = ++i;
          r.push(array[i]);
        }
        return r;
      }
      

43.异步加载js有哪些方式

  • onload时的异步加载

    • 这种方法只是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件触发的问题。

      注:DOMContentLoaded与load的区别。前者是在document已经解析完成,页面中的dom元素可用,但是页面中的图片,视频,音频等资源未加载完,作用同jQuery中的ready事件;后者的区别在于页面所有资源全部加载完毕。

    (function(){
    	if(window.attachEvent){
        	window.attachEvent("load", asyncLoad);
        }else{
        	window.addEventListener("load", asyncLoad);
        }
        var asyncLoad = function(){
        	var ga = document.createElement('script'); 
            ga.type = 'text/javascript'; 
            ga.async = true; 
            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
            var s = document.getElementsByTagName('script')[0]; 
            s.parentNode.insertBefore(ga, s);
        }
    })();
    
  • $(document).ready()

    需要引入jquery,兼容所有浏览器

    $(document).ready(function() {
         alert("加载完成!");
     });
    
  • <script>标签的async="async"属性

    <script type="text/javascript" src="xxx.js" async="async"></script>
    
    • async属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持
    • async属性规定一旦脚本可用,则会异步执行
    • async属性仅适用于外部脚本
    • 此方法不能保证脚本按顺序执行
    • 他们将在onload事件之前完成
  • <script>标签的defer="defer"属性

    <script type="text/javascript" defer></script>
    
    • defer属性规定是否对脚本执行进行延迟,直到页面加载为止
    • 如果脚本不会改变文档的内容,可将defer属性加入到<script>标签中,以便加快处理文档的速度
    • 兼容所有浏览器
    • 此方法可以确保所有设置了defer属性的脚本按顺序执行
  • es6模块type="module"属性

    <script type="module" src="XXX.js"></script>
    
    • 浏览器对于带有type=”module”的<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性 。如下:

    • ES6模块允许内嵌在网页中,语法行为与加载外部脚本一致,如下:

      <script type="module"> 
         import utils from "./utils.js"; 
         // other code 
      </script>
      
  • Script Dom Element

    (function(){
        var scriptEle = document.createElement("script");
        scriptEle.type = "text/javasctipt";
        scriptEle.async = true;
        scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
        var x = document.getElementsByTagName("head")[0];
        x.insertBefore(scriptEle, x.firstChild);		
     })();
    
    • async 属性是HTML5中新增的异步支持。此方法被称为Script DOM Element方法,但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。

      (function(){;
          var ga = document.createElement('script'); 
          ga.type = 'text/javascript'; 
          ga.async = true; 
          ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
          var s = document.getElementsByTagName('script')[0]; 
          s.parentNode.insertBefore(ga, s); 
      })();
      
  1. 什么是XSS攻击,如何防御
  • XSS(Cross Site Scripting),即跨站脚本攻击,是一种常见于web应用程序中的计算机安全漏洞.XSS通过在用户端注入恶意的可运行脚本,若服务器端对用户输入不进行处理,直接将用户输入输出到浏览器,然后浏览器将会执行用户注入的脚本。
  • 使用过滤用户输入的方法对恶意脚本进行过滤
    • 获取用户输入,不用.innerHTML,用innerText。
    • 对用户输入进行过滤,如 HTMLEncode 函数实现应该至少进行 & < > " ’ / 等符号转义成 &amp &lt &gt &quot &#x27 &#x2F;

45.什么是sql注入,如何防范

  • sql注入是一种将sql代码添加到输入参数中,传递到sql服务器解析并执行的一种攻击手法,sql注入攻击就是输入参数未经过滤,直接拼接到sql语句中,解析执行,达到预想之外的行为。

  • 如何防范

    • 严格检查输入变量的类型和格式

      • 1.对数字类型的参数id的强校验(empty()为空验证和is_numeric()进行数字验证)
      • 2.对字符串类型的参数的校验 (正则校验)
    • 过滤和转义特殊字符

      • 用php函数addslashes()进行转义, 一般是对这些特殊字符进行转义:

        1.单引号(’) 2.双引号(") 3.反斜杠(\) 4. NULL

      • 用mysqli的php扩展中的函数 mysqli_real_escape_string()

      • 利用预编译机制(mysqli 和 pdo)

        • mysqli预编译示例
        <?php
             
                $mysqli = new mysqli("localhost","root","root","dbname");
                $mysqli->query("set names utf8");
                $sql = 'insert into user(id,name,age,email) values (?,?,?,?)';
                $mysqli_stmt = $mysqli->prepare($sql);
             
             
                $id = 2;
                $name = 'kung';
                $age = 28;
                $email = 'ohdas@163.com';
                
                $mysqli_stmt->bind_param('isis',$id,$name,$age,$email);
             
                $res = $mysqli_stmt->execute();
             
                if(!$res){
                    echo 'error'.$mysqli_stmt->error;
                    exit;
                }else{
                    echo 'ok';
                }
             
                $id = 3;
                $name = 'xiaoyu';
                $age = 28;
                $email = 'kung-yu@163.com';
             
                $mysqli_stmt->bind_param('isis',$id,$name,$age,$email);
                $res = $mysqli_stmt->execute();
             
                if(!$res){
                    echo 'error'.$mysqli_stmt->error;
                    exit;
                }else{
                    echo 'ok';
                }
            ?>
        
        • PDO预编译示例

          <?php
              $dns = 'mysql:dbname=dbname;host=127.0.0.1';
              $user = 'root';
              $password = 'root';
          try{    
              $pdo = new PDO($dns,$user,$password);
          } catch(PDOException $e){
              echo $e->getMessage();
          }
              $pdo->query("set names utf8");
              
              $sql = 'inser into user values(:id,:name,:age,:email)';
              $pdo_stmt = $pdo->prepare($sql);
              
              $id = 2;
              $name = 'kung';
              $age = 27;
              $email = 'ohdas@163.com';
           
              $pdo_stmt->bindParam(':id',$id);
              $pdo_stmt->bindParam(':name',$name);
              $pdo_stmt->bindParam(':age',$age);
              $pdo_stmt->bindParam(':email',$email);
              $pdo_stmt->execute();
          ?>
          
      • DQL语句预编译(mysqli示例)

        <?php
            $mysqli = new mysqli("localhost","root","root","dbname");
            $mysqli->query("set names utf8");
            $sql = " select id,name from user where id > ?";
            $mysqli_stmt = $mysqli->prepare($sql);
            
            $id = 1;
            $mysqli_stmt->bind_param('i',$id);
            $mysqli_stmt->bind_result($id,$name);
            $mysqli_stmt->execute();
            
            while($mysqli_stmt->fetch()){
                echo $id.'--'.$name;
            }
         
            $mysqli_stmt->close();
            $mysqli->close();
        ?>
        

46.什么是csrf攻击

  • CSRF(Cross-site request forgery)也被称为 one-click attack或者 session riding,中文全称是叫跨站请求伪造
  • 如何防范
    • 验证HTTP Referer字段
    • 使用验证码
    • 在请求地址中增加token并验证
    • 在HTTP头中自定义属性并验证

47.什么是防抖和节流,怎么优化

  • 防抖
    • 高频率事件在n秒内只触发一次,如果再次触发,则重新计时。
    • 解决方案:设置定时器setTimeout,当n秒内再次触发时,清除定时器clearTimeout
    • 对于按钮防点击来说的实现:如果函数是立即执行的,就立即调用,如果函数是延迟执行的,就缓存上下文和参数,放到延迟函数中去执行。一旦我开始一个定时器,只要我定时器还在,你每次点击我都重新计时。一旦你点累了,定时器时间到,定时器重置为 null,就可以再次点击了。
    • 多数用在用户注册时手机号和邮箱验证
  • 节流
    • 高频率事件在n秒内只触发了一次,n秒内不再触发
    • 多数在监听页面元素滚动事件的时候会用到
    • 每次触发事件时都判断当前是否有等待执行的延时函数。
    • 解决方法:声明一个变量当标志位,记录当前代码是否在执行,如果空闲,就正常触发方法执行,如果代码正在执行,就取消这次执行,直接return。
    • 使用时间戳

48.同源策略

  • 协议,域名,端口号都相同的称之为同源,有一个不同则为非同源在这里插入图片描述

  • 同源策略限制的情况:

    • Cookie、LocalStorage 和 IndexDB 无法读取
    • DOM 和 Js对象无法获得
    • AJAX 请求不能发送
  1. 箭头函数和普通函数的区别
  • 箭头函数是匿名函数,不能作为构造函数,不能使用new
  • 箭头函数不能绑定arguments,取而代之用rest参数…解决
  • 箭头函数没有原型属性
  • 箭头函数的this永远指向其上下文的this,没有办改变其指向,
    普通函数的this指向调用它的对象
  • 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值

50.在css中哪个属性会影响DOM读取文档流的顺序

  • writing-mode(CSS3)
    • writing-mode:horizontal-tb;//默认值 :水平方向,从上倒下
    • writing-mode:vertical-rl ; //垂直方向,从右向左
    • writing-mode : vertical-lr; //垂直方向,从左向右
  • direction:
    • ltr :默认,文本从左到右
    • rtl:从右向左
    • inherit:继承父元素
  • unicode-bidi 属性设置文本的方向
    • normal
    • embed
    • bidi-override

51… js对象深复制的过程思路

  • 判断target是否存在,不存在返回空
  • 存在,获取所有的属性名
  • 遍历属性名
  • 获取描述对象
  • 判断值的类型:日期型,正则型,HTML型,函数型
  • 定义对象的属性:可读性,不可删除型,不可枚举型,值
  • 复制对象,递归调用
  1. get和post的区别
  • POST用body传输数据,而GET用url传输,GET不如POST安全
  • Get传送的数据量较小,这主要是因为受URL长度限制
  • 在这里插入图片描述

在js中什么是伪数组,怎么将伪数组转换为普通数组

  • 这里把符合以下条件的对象称为伪数组:

    • 具有length属性
    • 按索引方式存储数据
    • 不具有数组的push,pop等方法
  • 伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,不具有数组的push,pop等方法,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用document.getElementsByTagName, document.childNodes之类的,它们返回的NodeList对象都属于伪数组

  • 可以使用以下函数将伪数组转化为真正的Array对象(兼容问题处理)try catch

    function  makeArray(c) {
        try{
    	return Array.prototype.slice.call(c);
        }catch(e){
    		var ret = [],i, len = c.length;
            for(i = 0; i < len; i++) {
                ret[i] = (c[i]);
            }
            return ret;
        }
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值