前端开发

前端面试题

2019-03-01  本文已影响281人  沐雨芝录

1、\color{#8A00D3}{什么是盒子模型}
由元素内容,border,margin,padding四部分组成盒子模型。


2、\color{#8A00D3}{行内元素有哪些?块级元素有哪些? 空(void)元素有那些?}
行内元素:a、b、span、img、input、strong、select、label、em、button、textarea
块级元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote
空元素:即系没有内容的HTML元素,例如:br、meta、hr、link、input、img


3、\color{#8A00D3}{src和href的区别?}
src是引入外部资源,比如,js,css。
href是建立和当前元素和跳转页面之间的链接,用于超链接。


4、\color{#8A00D3}{怎样添加、移除、移动、复制、创建和查找节点?}
1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点

2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入

3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性


5、\color{#8A00D3}{数组去重}
[...new Set([1,2,3,1,'a',1,'a'])]


6、\color{#8A00D3}{统计字符串/数组 中字母个数或统计最多字母数}

        //字符串
        var strs = "asdasdadd";
        function getmaxstr(str){
            if(str.length == 1){return str;}
            var newarr = [];
            for(var i = 0 ; i<str.length; i++ ){
                if(!newarr[str.charAt(i)]){
                    newarr[str.charAt(i)] = 1;
                }else{
                    newarr[str.charAt(i)] +=1;
                }
            }
            console.log(newarr);
            var maxkey='';
            var maxvalue=1;//设定一个值
            for(var k in newarr){
                if(newarr[k]> maxvalue){//根据这个值做判读 将数组中的每个元素 与这个值做比较!
                    maxvalue = newarr[k];//出现的次数
                    maxkey = k;//次数最多的 字母
                }
            }
            console.log(maxkey);
            return maxvalue;
        }
        getmaxstr(strs);

        //计算数组中每个元素出现的次数
        var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

        var countedNames = names.reduce(function (allNames, name) { 
          console.log(allNames, name)
          if (name in allNames) {
            allNames[name]++;
          }
          else {
            allNames[name] = 1;
          }
          return allNames;
        }, {});
        console.log(countedNames)

7、\color{#8A00D3}{写一个function,清除字符串前后的空格。(兼容所有浏览器)?}

    function strTrim(str){
      if(!String.prototype.trim){
        return str.replace(/^\s+/,'').replace(/\s+$/,'');
      }else{
        return str.trim();
      }   
    }

8、\color{#8A00D3}{使用正则表达式验证邮箱格式?}
^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$


9、\color{#8A00D3}{你是如何推动你们的框架的,你是如何给框架升级的?}
首先在架构项目前思考:
① 如何将一个复杂的页面拆分为一个个独立的页面组件模块
② 如何将分拆后的业务组件模块重新合为一个完整的页面
③ 从重构角度看组件化开发带来的好处
④ 从前端优化的角度看待组件化开发


10、\color{#8A00D3}{title与h1的区别,b与strong的区别,i与em的区别?}
首先要明白的是什么是物理元素,什么是逻辑元素?title,b,i是物理行为,比如b告诉浏览器我加粗了,而h1,strong,em是逻辑行为,通过语义化方式告诉浏览器我是重要的。


11、\color{#8A00D3}{给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡,先执行冒泡还是捕获?}
捕获先于冒泡。顶部捕获=>底部冒泡=>第二层捕获=>第二层冒泡。


12、\color{#8A00D3}{viewport与rem布局}
viewport 是用户网页的可视区域。
viewport的大小决定了,css中的设置多少像素能刚好占满屏幕。例如,viewport=320,那么设置div的宽度为320px,则div刚好能占满屏幕
viewport的大小由width于scale共同决定,只设置width如果大于屏幕会出现滚动条,rem布局图片,宽高,布局等等,font-size用媒体查询解决。
dpr=物理像素/css像素(window.devicePixelRatio)


13、\color{#8A00D3}{浏览器缓存}
分为强缓存和协商缓存
协商缓存:Etag/If-None-Match

为什么有了Last-Modified还要Etag

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

Etag 的实现

在node 的后端框架express 中引用的是npm包etag,etag 支持根据传入的参数支持两种etag的方式:
一种是文件状态(大小,修改时间),另一种是文件内容的哈希值。


14、\color{#8A00D3}{函数节流和函数防抖}
函数节流是指一定时间内js方法只跑一次。
函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。


15、\color{#8A00D3}{XSS与CSRF攻击}

XSS:跨站脚本(Cross-site scripting),通过客户端脚本语言(如JavaScript)在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS。

XSS类型:

反射型:经过后端,不经过数据库
存储型:经过后端,经过数据库
DOM:不经过后端

XSS防御:

1.白名单重新整理,用户输入的html,遍历树节点拿到数据,重新构造dom
树,树中标签,属性从白名单中获取,不能识别的则丢弃。
2.过滤器对请求中的特殊字符进行编码转化,如< 转码为 &lt。.
3.对表单内容做长度校验,长度短,无法输入攻击代码。

CSRF:跨站请求伪造(Cross-site request forgery),冒充用户发起请求,完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

CSRF防御:

1.那就使用token吧,服务端生成随机码给前端。

16、\color{#8A00D3}{事件中target、this、currentTarget的区别}
target是触发事件对象,冒泡的时候指向子。
currentTarget 恒等于 this ,是绑定事件的对象,冒泡的时候指向父。


17、\color{#8A00D3}{输入url整个过程。}

  1. 网络传输:输入网址 =>dns解析ip=>TCP三次握手=>发送http请求=>服务器重定向=>处理请求,返回http响应=>得到数据。
  2. dom渲染:构建dom树(构建dom节点)=>构建渲染树(解析样式信息)=>布局渲染树(布局dom节点)=>绘制渲染树(绘制dom节点)。

18、\color{#8A00D3}{WebSocket}
前端:

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
}; 

服务端:

var ws = require("nodejs-websocket");
console.log("开始建立连接...")

var game1 = null,game2 = null , game1Ready = false , game2Ready = false;
var server = ws.createServer(function(conn){
    conn.on("text", function (str) {
        console.log("收到的信息为:"+str)
        if(str==="game1"){
            game1 = conn;
            game1Ready = true;
            conn.sendText("success");
        }
        if(str==="game2"){
            game2 = conn;
            game2Ready = true;
        }

        if(game1Ready&&game2Ready){
            game2.sendText(str);
        }

        conn.sendText(str)
    })
    conn.on("close", function (code, reason) {
        console.log("关闭连接")
    });
    conn.on("error", function (code, reason) {
        console.log("异常关闭")
    });
}).listen(8001)
console.log("WebSocket建立完毕")

19、\color{#8A00D3}{顺序存储结构和链式存储结构的优缺点比较}
① 顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。
优点:存储密度大(=1),存储空间利用率高。缺点:插入或删除元素时不方便。

②链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针。
优点:插入或删除元素时很方便,使用灵活。缺点:存储密度小(<1),存储空间利用率低。


20、\color{#8A00D3}{CROS跨域资源共享}

  1. 简单请求:get, post
    服务端设置:Access-Control-Allow-Origin: "*"
    前端不需要。
  2. 非简单请求:put,delete
    服务端设置:Access-Control-Allow-Origin: "*"; 还需要设置method和header
    前端需要设置header。

21、\color{#8A00D3}{桌面应用做过吗?}
神奇的Electron

21、\color{#8A00D3}{React的setState到底做了什么?}
如下代码:

class App extends React.Component {
   constructor() {
       super();
       this.state = {
           num: 0
       }
   }
   componentDidMount() {
       for ( let i = 0; i < 10; i++ ) {
           this.setState( {num: this.state.num + 1} );
           console.log(this.state.num) // 10次0
       }
   }

   render() {
       return ( <div className='App'>
           <h1>{this.state.num}</h1>
       </div> );
   }
}

原因在于,当你传一个普通的对象 this.setState( {num: this.state.num + 1} ) 时,他会进入队列,队列里就做一件事 Object.assign( this.state, stateChange ) ,this.state永远都是之前的0。
100次以后就通过 flush 方法清空队列,包裹flush的是 **Promise.resolve().then(flush) **,使用微异步跳出队列,渲染页面。

componentDidMount() {
       for ( let i = 0; i < 10; i++ ) {
        this.setState( prevState => {
            console.log( prevState.num ); // 打印1-9
            return {
                num: prevState.num + 1
            }
        } );
    }
    }

原来setState支持传函数,这样它内部通过递归方式获取前一个值,就可以做到累加,并且还只会渲染一次页面,多神奇。

上一篇 下一篇

猜你喜欢

热点阅读