2018 浅谈前端面试那些事 (24min的答案总结)

整理该篇博客部分知识点的答案:https://blog.csdn.net/snsHL9db69ccu1aIKl9r/article/details/79894467

<!--菜鸟一枚,若有错误地方,请指出~-->

1.HTML5新特性?什么是语义化

    html5新特性: H5新特性
    语义化:语义化是指用合理HTML标记以及其特有的属性去格式化文档内容。通俗地讲,语义化就是对数据和信息进行处理,使得机器可以理解.
   语义化的(X)HTML文档有助于提升你的网站对访客的易用性,比如使用PDA、文字浏览器以及残障人士将从中受益。对于搜索引擎或者爬虫软件来说,则有助于它们建立索引,并可能给予一个较高的权值。

2.浏览器的标准模式和怪异模式

     在标准模式页面按照HTML,CSS的定义渲染,而在怪异模式就是浏览器为了兼容很早之前针对旧版本浏览器设计,并未严格遵循W3C标准而产生的一种页面渲染模式
(1) 盒模型
    元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分组成了css中的盒模型。

  IE盒子模型和标准W3C盒子模型:ie的width包括:padding\border。标准的width不包括:padding\border

(2)图片元素的垂直对齐方式

       对于inline元素和table-cell元素,标准模式下vertical-align属性默认取值为baseline,在怪异模式下,table单元格中的图片的vertical-align属性默认取值为bottom,因此在图片底部会有及像素的空间。搜索搜索搜索

(3)<table>元素中的字体

      CSS中,对于font的属性都是可以继承的,怪异模式下,对于table元素,字体的某些元素将不会从body等其他封装元素中继承得到,特别是font-size属性。

(4)内联元素的尺寸

   标准模式下,non-replaced inline元素无法自定义大小,怪异模式下,定义这些元素的width,height属性可以影响这些元素显示的尺寸。

(5)元素的百分比高度:

    a:CSS中对于元素的百分比高度规定如下:百分比为元素包含块的高度,不可为负值,如果包含块的高度没有显示给出,该值等同于auto,所以百分比的高度必须在父元素有高度声明的情况下使用。

扫描二维码关注公众号,回复: 2285038 查看本文章

    b:当一个元素使用百分比高度时,标准模式下,高度取决于内容变化,怪异模式下,百分比高度被正确应用。

(6)元素溢出的处理:

     标准模式下,overflow取默认值visible,在怪异模式下,该溢出会被当做扩展box来对待,即元素的大小由其内容决定,溢出不会裁减,元素框自动调整,包含溢出内容。

PS:在js中如何判断当前浏览器正在以何种方式解析?

    document对象有个属性compatMode,它有两个值:BackCompat对应quirks mode(怪异模式),CSS1Compat对应strict mode(标准模式)

3.xhtml和html的区别

HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言。HTML 和 XHTML 的区别简单来说,XHTML 可以认为是 XML 版本的 HTML,为符合 XML 要求,XHTML 语法上要求更严谨些。
以下是 XHTML 相对 HTML 的几大区别:
  XHTML 要求正确嵌套
  XHTML 所有元素必须关闭
  XHTML 区分大小写
  XHTML 属性值要用双引号
  XHTML 用 id 属性代替 name 属性
  XHTML 特殊字符的处理

4.meta标签

<meta> 标签提供关于 HTML 文档的元数据。

它不会显示在页面上,但是对于机器是可读的。可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务.meta里的数据是供机器解读的,告诉机器该如何解析这个页面,还有一个用途是可以添加服务器发送到浏览器的http头部内容。meta标签的常用属性:

(1)charset(声明文档使用的字符编码),通常有以下两种方式的写法(两种写法是等效的):

<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

(2)百度禁止转码(百度会自动对网页进行转码,这个标签是禁止百度的自动转码)

<meta http-equiv="Cache-Control" content="no-siteapp" />

(3)viewport(主要是影响移动端页面布局的

content 参数:

width viewport 宽度(数值/device-width)

height viewport 高度(数值/device-height)

initial-scale 初始缩放比例

maximum-scale 最大缩放比例

minimum-scale 最小缩放比例

user-scalable 是否允许用户缩放(yes/no)

<meta name="viewport" content="width=device-width, initial-scale=1.0">

(4)...more 还有更多关于meta属性的用法设置。设置不同浏览器的解析方式等。更多详情请看meta标签

5.canvas

Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表、动画等。
<canvas> 标签只是图形容器,您必须使用脚本来绘制图形

下面的代码是用Canvas绘制的一个红色的矩形:

<!DOCTYPE HTML>
<html>
<body>
<canvas id="myCanvas">your browser does not support the canvas tag </canvas>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
var ctx=canvas.getContext('2d');
ctx.fillStyle='#FF0000';  //设置属性
ctx.fillRect(0,0,80,100);//根据坐标画出正方形
</script>
</body>
</html>

6.css js放置位置,以及这样放置的原因

说到css js放置位置的问题,我们就有必要先了解一下网站加载的整个完整过程了。
(1).首先浏览器从服务器接收到html代码,然后开始解析html
(2).构建DOM树(根据html代码自顶向下进行构建),并且在同时构建渲染树
(3).遇到js文件加载执行,将阻塞DOM树的构建;遇到css文件,将阻塞渲染树的构建
(script标签中的defer属性:构建DOM树的过程和js文件的加载异步(并行)进行,但是js文件执行需要在DOM树构建完成之后
   script标签中的async属性:构建DOM树、渲染树的过程和js文件的加载和执行异步(并行)进行)

   所以script标签最好放在</body>标签的前面,因为放在所有body中的标签后面就不会出现网页加载时出现空白的情况,可以持续的给用户提供视觉反馈,同时在有些情况下,会降低错误的发生。
   而css标签应该放在<head></head>标签之间,因为如果放在</body>标签的前面,那么当DOM树构建完成了,渲染树才构建,那么当渲染树构建完成,浏览器不得不再重新渲染整个页面,这样造成了资源的浪费。效率也不高。如果放在<head></head>之间,浏览器边构建边渲染,效率要高的多。

总的来说,就是提高性能,提高网页的可读性。

7.什么是渐进式渲染

       渐进式渲染很好理解,其实就是在首次渲染的时候,只加载首屏的内容,随着用户滑动或者说时间的推移,才进行后面的加载。这样做的好处是:提高网页的性能,不会早成资源的浪费,按需加载。

=========ES6篇======

8.谈一谈 promise

     Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。Promise是一个容器,里面保存着某个未来才会结束的事件的结果(异步操作)。Promise对象有三种状态,分别是pending(进行中),fulfilled(已成功)以及rejected(已失败)。只有异步操作的结果才可以决定当前是哪一种状态,任何其它操作都无法改变这个状态。但是一旦异步操作的结果使得Promise的状态改变,那么Promise的状态就不会再变,在任何时候,我都可以得到这个结果,此时就称谓resolved(已定型)。状态的改变有以下两种情况发生:从pending变成fullfilled(成功)以及从pending变为rejected(失败)。

9.如果遇到一个东西不知道是 ES6 还是 ES5, 你该怎么区分它

       这道题我也不知道怎么回答,百度了一下,发现也没有合适的答案。比如说,你看到有调用对象abc();但是你不知道它是属于es5还是es6的写法。那如果是我的话,我应该会这么回答,第一,我不知道它是属于哪一种,那么也就是说我自己没有这个能力来回答问题,但不代表网上的大牛不知道,所以第一步是先百度,其次要是百度不到,可以向同事请教。

10.es6的继承和es5的继承有什么区别

ES5:Javascript利用原型链的特性来实现继承,通过将子类构造函数的原型作为父类构造函数的实例(sub.prototype=new super)。

function teacher(name){  
    this.name = name;  
}  
teacher.prototype.sayName = function(){  
    console.log("name is "+this.name);  
}  
var teacher1 = new teacher("xiaoming");  
teacher1.sayName();  
  
function student(name){  
    this.name = name;  
}  
student.prototype = new teacher()  
var student1 = new student("xiaolan");  
student1.sayName();  
//  name is xiaoming  
//  name is xiaolan  
注:【new操作到底做了哪些事?】
var Person = function(){};
var p = new Person();
 new(实例化)的过程拆分成以下三步:
   (1) var p={}; 也就是说,初始化一个对象p
   (2) p.__proto__ = Person.prototype;
   (3) Person.call(p); 也就是说构造p,也可以称之为初始化p

ES6:ES6封装了class,extends关键字来实现继承(跟Java的语法比较像),内部的实现原理其实依然是基于上面所讲的原型链,不过进过一层封装后,Javascript的继承得以更加简洁优雅地实现。

class A {
  static hello() {
    console.log('hello world');
  }
}

class B extends A {
}

B.hello()  // hello world

11.使用promise来封装ajax

function getJSON (url) {
    return new Promise( (resolve, reject) => {
        var xhr = new XMLHttpRequest()
        xhr.open('GET', url, true)

        xhr.onreadystatechange = function () {
            if (this.readyState === 4) {
                if (this.status === 200) {
                    resolve(this.responseText, this)
                } else {
                    var resJson = { code: this.status, response: this.response }
                    reject(resJson, this)
                }
            }
        }

        xhr.send()
    })

}
具体的封装请看这里

12.let ,const的优点

let是修复了var的作用域的一些bug,变的更加好用。

let是更好的var。var的作用于是函数作用域,而let是块级作用于域

const声明的变量只可以在声明时赋值,不可随意修改,这是最大的特点。

let与const

13.ES6和node的commonjs模块化规范区别

es6 {
      export   :      '可以输出多个,输出方式为 {}' ,
      export  default : ' 只能输出一个 ,可以与export 同时输出,但是不建议这么做',
      解析阶段确定对外输出的接口,解析阶段生成接口,
      模块不是对象,加载的不是对象,

      可以单独加载其中的某个接口(方法),

     静态分析,动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变,

    this 指向undefined

}

commonJS {

module.exports =  ...   :      '只能输出一个,且后面的会覆盖上面的' ,

exports. ...  : ' 可以输出多个',

运行阶段确定接口,运行时才会加载模块,

模块是对象,加载的是该对象,

加载的是整个模块,即将所有的接口全部加载进来,

输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,

this 指向当前模块

}

es6模块与 commonJS规范的区别

14.es6 generator 是什么,async/await 实现原理

      Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。但是Generator 函数与传统函数相比有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”,且yield不能再其它传统函数中执行)

     async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args) {
  // ...
}

// 等同于

function fn(args) {
  return spawn(function* () {
    // ...
  });
}

15.箭头函数,以及它的this指针

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。在箭头函数中,this是固定的。

15.1  es6模块管理是支持模块的循环依赖吗?如果支持,那么是如何支持模块循环依赖的,并请举例说明;如果不支持,请回答不支持的原因。

支持!

// even.js
import { odd } from './odd'
export var counter = 0;
export function even(n) {
  counter++;
  return n === 0 || odd(n - 1);
}

// odd.js
import { even } from './even';
export function odd(n) {
  return n !== 0 && even(n - 1);
}
运行这段代码
$ babel-node
> import * as m from './even.js';
> m.even(10);
true
> m.counter
6

在执行evev.js的时候,发现加载了odd.js,所以在es6中,会优先执行odd.js,然后再来执行 even.js。所以在运行的时候,m.even(10);参数先会经过odd.js,此时n就等于9,进入even.js;然后counter+1;n在减一.直到n等于0的时候,此时counter的值为6。

==========js篇=======

16.js的基本类型有哪些?引用类型有哪些?null和undefined的区别

     js的基本数据类型:Undefined  Null  Boolean  Number  String

     引用类型:function object array

    null和undefined的区别:

   null表示"没有对象",即该处不应该有值;

   undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。

17.Object是引用类型嘛?引用类型和基本类型有什么区别?哪个是存在堆哪一个是存在栈上面的?

object是引用类型。

区别:

(1)基本类型的值是不可变的(或者说原始的的值不会改变,当调用某些方法使其改变的时候,实际上返回的是一个新的字符串),但引用类型的值可以改变

(2)基本类型的比较是值的比较:只有在它们的值相等的时候它们才相等

    引用类型的比较是引用的比较,就是比较两个对象的堆内存中的地址是否相同。

基本类型的变量是存放在栈区的,引用类型的值是同时保存在栈内存和堆内存中的对象

18.JS常见的dom操作api

    详情见:js的dom操作API

19.解释一下事件冒泡和事件捕获

<div id="outer">
    <p id="inner">Click me!</p>
</div>

   上面的代码当中一个div元素当中有一个p子元素,如果两个元素都有一个click的处理函数。那么我们怎么才能知道哪一个函数会首先被触发呢?

事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象

事件捕获与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document

而在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p

20.如何理解闭包?谈谈闭包的优缺点。

      当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其它变量,如果返回的这个函数在外部被执行,就产生了闭包。

 下面看个例子:

function add() {
    var counter = 0;
    return counter += 1;
}
 
add();
add();
add();
 
// 本意是想输出 3, 但事与愿违,输出的都是 1 !

这段代码,我想在每次调用的时候,n的值加1,但是上面的写法,却输出的都是一样的结果,也就是,只会输出1。那么使用闭包来改造一下上述函数,就可以达到,每次输出都加一的需求。

function add(){
  var counter = 0;
  return function(){
  return counter+=1;
}
var Fanjf = add();
console.log(Fanjf());//1
console.log(Fanjf());//2
console.log(Fanjf());//3
}

这样就可以了,下面的代码将展示一套完整的计数。(采用ES6编写)

<!DCOTYPE>
<html>
	<head>
		<title>计数</title>
		<script>
function add() {
    let counter = 0;
   return  ()=>  counter += 1;
    	};
let s =add();
function myFunction(){
    document.getElementById("abc").innerHTML = s();
}
  </script>
	</head>
	<body>
<button class="btn" onclick="myFunction();" >计数</button>
	<div id="abc"></div>
</body>
</html>

使用闭包的注意点
1)滥用闭包,会造成内存泄漏:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)会改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

21.this有哪些使用场景?

(1).在html元素事件属性中使用。比如:

<input type=”button” onclick=”showInfo(this);” value=”点击一下”/>

不过需要注意的是,在js中定义showInfo函数的时候,传入的参数不能为this,可以换个名字来接收this指针,比如说that,_this等。具体请看下方代码:

<!DCOTYPE>
<html>
  <head>
  <title>this获取html元素的各个值</title>
  <script>
  function showInfo(_this) {
	let value = _this.value;
	let type  = _this.type;
        console.log(value);
        console.log(type);
    	};
  </script>
  </head>
  <body>
    <input type="button" onclick="showInfo(this);" value="点击" />
  </body>
</html>

(2).构造函数

<!DCOTYPE>
<html>
	<head>
		<title>this获取html元素的各个值</title>
		<script>
                function animal(name,color) {
	             this.name12 = name;
	             this.color12 = color;
	             console.log(name12);
	             console.log(color12);
                 };
             animal('tiger','yellow');
              </script>
	</head>
</html>

(3)input点击,获取值

<input type="button" id="text" value="点击一下" />
<script type="text/javascript">
    var btn = document.getElementById("text");
    btn.onclick = function() {
        alert(this.value);    //此处的this是按钮元素
    }
</script>

(4) apply()/call()求数组最值

var  numbers = [5, 458 , 120 , -215 ]; 
var  maxInNumbers = Math.max.apply(this, numbers);  
console.log(maxInNumbers);  // 458
var maxInNumbers = Math.max.call(this,5, 458 , 120 , -215); 
console.log(maxInNumbers);

上述代码在ES6中还可以使用 ... 符号,做进一步改进,如下代码所示:

<!DCOTYPE>
<html>
  <head>
  <title>11111111111133333334444444444444444444</title>
	<script>
             let  numbers = [5, 458 , 120 , -215 ]; 
             let  maxInNumbers = Math.max(...numbers);  
             console.log(maxInNumbers);  // 458
             let maxInNumbers11 = Math.max.call(this,5, 458 , 120 , -215); 
             console.log(maxInNumbers11);
         </script>
	</head>
	<body>
</body>
</html>

22.显示原型和隐式原型,原型链是什么?为什么要有原型链       

显示原型:prototype

隐式原型:在一般环境下无法访问,即不可见,在FireFox下可以通过__proto__方式访问;隐式原型链用于javascript引擎内部对原型链的搜寻,通过显示原型链来设置。

原型链是什么?JavaScript对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链

为什么要有原型链?许多OO语言支持两种继承方式:接口继承和实现继承。 
接口继承只继承函数签名,实现继承则继承实际的方法。 
由于函数无签名,在JavaScript中无法实现接口继承。所以只能实现方法继承。
实现继承主要依赖原型链。

=======

猜你喜欢

转载自blog.csdn.net/qq_36626755/article/details/79912411
今日推荐