手记

12个常规前端面试题及小结

原文链接:xingxin.me
这是昨天对一个新来有两月妹纸的一个小测试,总体来说都很简单常规,但结果有点儿不理想,今天把它总结总结记下来。

1.简述一下你对HTML语义化的理解?并写出一段语义化的HTML?

语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化),便于开发者阅读和写出更优雅的代码的同时,让浏览器的爬虫和机器很好的解析。

  • 用正确的标签做正确的事情
  • html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析
  • 语义化的HTML在没有CSS的情况下也能呈现较好的内容结构与代码结构
  • 搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO;
  • 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解
  • HTML5增加了许多语义化标签如:header footer nav article ……

语义化HTML示例:

<!-- 这是开放的 -->
<header>
    <h1>header</h1>
</header>
<section class="main">
  main
</section>
<aside>aside</aside>
<footer>
  footer
</footer>

2. HTML5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

HTML5 是定义 HTML 标准的最新的版本。 该术语表示两个不同的概念:

  • 它是一个新版本的HTML语言,具有新的元素,属性和行为,
  • 它有更大的技术集,允许更多样化和强大的网站和应用程序。这个集合有时称为HTML5和朋友,通常缩写为HTML5

HTML5新特性:

  • HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加
  • 绘画 canvas;
  • 用于媒介回放的 video 和 audio 元素;
  • 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失
  • sessionStorage 的数据在浏览器关闭后自动删除
  • 语意化更好的内容元素,比如 articlefooterheadernavsection
  • 表单控件,calendardatetimeemailurlsearch
  • 新的技术webworker, websocket, Geolocation

移除元素:

  • 纯表现的元素basefontbigcenterfont, sstrikettu
  • 对可用性产生负面影响的元素:frameframesetnoframes

处理HTML5新标签的浏览器兼容问题:

  • IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签,浏览器支持新标签后,还需要添加标签默认的样式。

  • 可直接使用成熟的框架、比如html5shiv
    <!--[if lt IE 9]>
    <script src="html5shiv.js"></script>
    <![endif]-->

如何区分 HTML 和 HTML5:

  • DOCTYPE声明
  • 新增元素

3. 为什么要初始化CSS样式(reset css)

  • 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异

  • 最简单粗暴的

    * {
       margin: 0;
       padding: 0;
    }
  • 更好的选择Normalize.css 相比于传统的CSS reset,Normalize.css是一种现代的、为HTML5准备的优质替代方案

  • Reset CSS:只选对的,不选"贵"的,因根据具体项目来做选择权衡,不应该滥用

4. css定义的权重?

页面显示样式的优先级取决于其“特殊性”’,特殊性越高,就显示最高的,当特殊性相等时,显示后者

特殊性表述为4个部分:0,0,0,0

一个选择器的特殊性如下确定:

  • 对于选择器是#id的属性值,特殊性值为:0,1,0,0
  • 对于属性选择器,class或伪类,特殊性值为:0,0,1,0
  • 对于标签选择器或伪元素,特殊性值为:0,0,0,1
  • 通配符‘*’对特殊性值为:0,0,0,0
  • 内联样式特殊性值为:1,0,0,0

5. 讲讲position的值relativeabsolute的区别?

  • absolute:生成绝对定位的元素,相对于值不为 static的第一个父元素进行定位

  • relative:生成相对定位的元素,相对于其正常位置进行定位

6. 如何水平垂直居中div(至少给出2种解决方法)

1.absolute + transform:

<div class="parent">
  <div class="child">Demo</div>
</div>

<style>
  .parent {
    position: relative;
  }
  .child {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
</style>

2.inline-block + text-align + table-cell + vertical-align

<div class="parent">
  <div class="child">Demo</div>
</div>

<style>
  .parent {
    text-align: center;
    display: table-cell;
    vertical-align: middle;
  }
  .child {
    display: inline-block;
  }
</style>

3.flex + justify-content + align-items

<div class="parent">
  <div class="child">Demo</div>
</div>

<style>
  .parent {
    display: flex;
    justify-content: center; /* 水平居中 */
    align-items: center; /*垂直居中*/
  }
</style>

更多布局示例请移步CSS常见布局解决方案 垂直居中,水平居中,各种布局

7. 渐进增强 VS 优雅降级,你怎么看?

渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验

优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览

二者如何抉择: 这是个人观点。。。

8. JavaScript 的数据类型

javascript有六种基本数据类型:UndefinedNullBooleanSymbol(es6)NumberString
还有一种复杂数据类型:对象

9. JavaScript 数组去重?(简述思路即可)

  • 遍历数组法: 这应该是最简单的去重方法(实现思路:新建一新数组,遍历数组,值不在新数组就加入该新数组中)

    // 遍历数组去重法
    function unique(arr){
    var _arr = []
    //遍历当前数组
    for(var i = 0; i < arr.length; i++){
      //如果当前数组的第i已经保存进了临时数组,那么跳过,
      //否则把当前项push到临时数组里面
      if (_arr.indexOf(arr[i]) == -1) _arr.push(arr[i])
    }
    return _arr
    }

    注意点:indexOf 为 ES5 的方法,注意浏览器兼容,需要自己实现 indexOf

  • 对象键值对(hash) 法:速度快,高效,占用更大的内存换取更快的时间,用 JavaScript 中的 Object 对象来当做哈希表,hash去重的核心是构建了一个 hash 对象来替代 indexOf

    // hash 去重法
    function unique(arr){
       var _arr = [], 
           hash = {}
       for (var i = 0; i < arr.length; i++) {
           var item = arr[i]
           var key = typeof(item) + item
            // 对象的键值只能是字符串, typeof(item) + item来去分1和'1'的情况
           if(hash[key] !== 1){
               _arr.push(item)
               hash[key] = 1
           }
       }
       return _arr
    }
  • 炫酷的 es6 Set数据结构: ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值

    function unique(arr){
      return Array.from(new Set(arr))
      // Array.from方法用于将两类对象转为真正的数组:
      // 类似数组的对象(array-like object)和可遍历(iterable)的对象
    }

关于 JavaScript 数组去重,还有很多很多可以讲,篇幅有限,这里介绍了几种常规的,更多的自己去探索

10. 看如下 JavaScript 代码,给出代码运行结果?(并简述原因)

var a = 2

function foo() {
  console.log(a) // 1.???
  console.log(bar())  // 2.???
  var a = 1
  function bar(){
    return a
  }
  console.log(bar())  // 3.???  
}

foo()
console.log(a) // 4. ???

代码运行结果: 1: undefined,2: undefined,3: 1,4: 2

这里考察了 JavaScript 的作用域和变量提升。

在 JavaScript 中,函数、变量的声明都会被提升(hoisting)到该函数或变量所在的 scope 的顶部

JavaScript 采用词法作用域(lexical scoping),也就是静态作用域,函数作用域在函数定义时就决定了 ,同时在es6 前 JavaScript是没有块级区域(block-level scope),而只有函数域 (function-level scope)。(在es6前我们可过闭包来实现类似块级作用域的效果)所谓函数作用域就是:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的

var a = 2
function foo() {
  // var a --> 变量提升
  console.log(a) // 1.???
  // 虽然在函数作用域里,这个 a 还未声明,
  // 实际上由于变量提升此刻的在函数头部已经定义了 a 只是尚未赋值 
  // 所以1处的值是undefined
  console.log(bar())  // 2.??? 
  // 理解了第一个第二个也不难了
  // 结果也为 undefined
  var a = 1
  function bar(){
    return a
  }
  console.log(bar())  // 3.???
  // 此刻a已经被赋值1
  // 结果为 1
}

foo()
console.log(a) // 4. ???
// 函数作用域不会对全局作用域产生影响,
// 结果为2

11. 使用原生ajax获取 Linus Torvalds 的GitHub信息(API:https://api.github.com/users/torvalds,如记不清具体代码简述过程即可),并将JSO N字符串解析为JSON对象,并讲讲对JSON的了解

这是对 ajax与json的考察

ajax的全称:Asynchronous Javascript And XML,异步传输+js+xml 现在差不多都用JSON

  1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象
  2. 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
  3. 设置响应HTTP请求状态变化的函数
  4. 发送HTTP请求
  5. 获取异步调用返回的数据
  6. 数据处理

下面就来贴代码吧:

var api = 'https://api.github.com/users/torvalds'
var xhr = new XMLHttpRequest() // 创建XMLHttpRequest对象

if(window.XMLHttpRequest){ // 兼容处理
    xhr = new XMLHttpRequest()
}else{
    xhr = new ActiveXObject('Microsoft.XMLHTTP')// 兼容ie6以下下
}

xhr.open('get',api,true)    //设置请求信息    
xhr.send()  //提交请求

//等待服务器返回内容
xhr.onreadystatechange = function() {
    if ( xhr.readyState == 4 && xhr.status == 200 ) {
         console.log(JSON.parse(xhr.responseText)) // 使用JSON.parse解析JSON字符串
    } 
}

上面这端代码应该就是最简单的一个完整的AJax,当然了,你可以对它进行各种封装,甚至结合promise,

async/await。。。

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小 如:{"age":"12", "name":"back"}

JSON.parse() 方法解析一个JSON字符串

JSON.stringify() 方法将一个JavaScript值转换为一个JSON字符串

eval也能解析JSON字符串,但不推荐

关于JSON就不多说了,前面写过一篇 JSON入门

12. 简单谈谈前端性能优化

  1. 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
  2. 减少DOM操作次数,优化javascript性能。
  3. 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
  4. 尽量避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
  5. 图片预加载,将样式表放在顶部,将脚本放在底部。
  6. 雪碧图
  7. ……太多了,一页纸都写不完

抛砖引玉

19人推荐
随时随地看视频
慕课网APP