前端面试1

2017-09-13  本文已影响0人  涯无凌

前端面试问题集锦


JavaScript 部分

1、JQuery $(document).ready() 和 window.onload 的区别

window.onload 必须等到页面全部元素(包括图片)加载完毕后才执行
$(document).ready() 是Dom结构绘制完毕后执行,不需要等到全部加载完成

2、数组去重

数组去重详解

3、=====
4、NaN

NaN 是数字类型

console.log(typeof NaN)   // number

NaN instanceof Number 返回false

涉及到 NaN 的情况都不能简单地使用运算符进行比较,需要使用isNaN()

5、垃圾回收机制

垃圾回收机制及优化

6、对 this 的理解

js 中的 this 取决于函数的调用方式。this 是运行时绑定,除了箭头函数,箭头函数是在定义时绑定的,指向父级函数

js 的一个特点:函数中存在 定义时上下文运行时上下文上下文是可以改变的 这些概念

7、继承

JavaScript 是一门基于原型的语言,继承分为 类式继承原型继承类式继承 通过 new 父类的 prototype 来继承方法,原型继承去掉了构造函数,但需要将对象的属性和方法写在一个 {} 声明中

8、setTimeoutsetInterval 的区别,如何相互实现

http://blog.csdn.net/baidu_24024601/article/details/51862488

区别:setInterval 在执行完一次代码后,经过固定的时间间隔会自动重复执行那段代码,而 setTimeout 只执行一次

setTimeout 实现 setInterval
核心:在延时的情况下递归调用自己

setTimeout(function () {
    doSomething();
    
    setTimeout(arguments.callee, 300);
}, 300)

function mySetInterval (callback, time) {
    setTimeout(function () {
        callback.call(this);
        
        setTimeout(arguments.callee, time);
    }, time);
}
// setInterval实现setTimeout
var timer = setInterval(function () {
    doSomething();
    clearInterval(timer);
}, 1000);

消除定时器:clearTimeout()clearInterval()

9、解决异步编程问题
10、js 的数据类型

最新的 ES 标准定义了7种数据类型

11、变量声明提升和函数声明提升

变量声明提升:通过 var 声明的变量在代码执行之前会被 js引擎 提升到当前作用域顶部
函数声明提升:通过函数声明的方式(非函数表达式)声明函数在代码执行之前会被 js引擎 提升到当前作用域顶部,而且函数声明提升优先级比变量声明提升要高

在严格模式下,函数声明只能在全局作用域或函数内,不能在 iffor 中,但在 ES6 中可以,ES6 支持了块级作用域

以下代码在ES5会报错,在ES6中不报错

if (1) {
    function method() {
    
    }
}
12、null和undefine区别

null 和 undefined 可被转化为 false

null 表示“没有对象”,即此处不应该有值,用法:

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

13、prototype__proto__ 的区别

几乎所有函数(除了一些内建函数)都有一个名为prototype的属性,这个属性是指向函数的原型对象,原型对象可以包含所有实例共享的属性和方法,原型对象的constructor又指回函数

实例化后的对象内部有个指针__proto__指向函数的原型

通过isPrototypeOf判断原型

Person.prototype.isPrototypeOf(person)

getPrototypeOf() 返回对象原型

hasOwnProperty() 可以检测一个属性是在实例中还是在原型中,当属性存在对象实例中,返回true

in操作符可以访问原型和实例的属性

检测在原型中的属性或方法:

function hasPrototypeProperty (object, name) {
    return !obj.hasOwnProperty(name) && (name in object);
}
14、作用域链及执行上下(context)
15、内存泄露及如何解决
16、web worker

web worker并不是虚拟线程而是真正实现了多线程,而setTimeout()可以说是伪线程

当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行

web worker 无法访问到window,document,parent对象

17、深拷贝和浅拷贝

JS 的深浅拷贝只针对复杂数据类型(Array,Object),因为原始类型的值存在于栈空间中,而JS可以直接操作栈空间

缺点是:1. 如果拷贝对象中有 function ,则拷贝之后会丢失这个function
2.如果拷贝对象中有正则表达式,则拷贝之后的对象正则表达式会变成Object

let a = {name: 'liyanfeng', sayName: function() {alert(this.name)}, numberReg: /\d+/}
let b = JSON.parse(JSON.stringify(a))
// sayName丢失,numberReg变为了对象
console.dir(b) // {name: 'liyanfeng', numberReg: {}} 

关于深浅拷贝的经典例子

let a = {name:1}
let b = a

console.log(a)  //1
console.log(b)  //1 这里b只是a的浅拷贝,是a的引用。即a,b指向同一块内存

b.name = 2
console.log(a)  //2
console.log(b)  //2 理由同上

let b ={ name:3 }
console.log(a)  //2
console.log(b)  //3 当b被覆盖时,b指向了一块新的内存,a还是指向原来的内存
18、事件委托(事件委托利用事件冒泡机制)

之所以这样实现事件委托原因:完整的事件流是从事件捕获开始的,再到触发该事件,最后到事件冒泡。根据这个过程,每个子元素li的点击事件最终会传递给ul,那么我们只需要监听ul的点击事件,然后判断目标元素的名称是不是我们寻找的元素(通过检查事件event的target)

document.getElementById('ul').addEventListener('click', function (e) {
    var event = e || window.event;
    var target = event.target || event.srcElement;
    if (target.name.toLowerCase() == 'li') {
        ...
    }
})
if (target.matches('class-name')) {
    ...
}

优点:

传统的事件写法函数较多,内存占用大,性能差,且必须事先声明

而事件委托只指定一个事件处理函数,即可处理某一类型的所有事件

19、DOM事件流

(1)三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

20、事件冒泡的兼容性问题
// 阻止事件冒泡的兼容性
function stopBubble (event) {
    var e = arguments.callee.caller.arguments[0] || event;
    if (e && e.stopPropagation) {
        e.stopPropagation();
    } else if (window.event) {
        window.event.cancelBubble = true;
    }
}

// 阻止浏览器默认行为的兼容性写法
function stopDefault (event) {
    var e = argument.callee.caller.arguments[0] || event;
    if (e && e.preventDefault) {
        e.preventDefault();
    } else {
        window.event.returnValue = false;
    }
}
21、new关键字

var obj = new Foo() 发生了什么

let obj = {}
obj.__proto__ = Foo.prototype
Foo.call(obj)
22、typeof和instanceof
23、如何解决多个Promise嵌套的问题

promise链式调用

var p1 = new Promise(function() {});
var p2 = new Promise(function() {});
var p3 = new Promise(function() {});
// var p4...

p1.then(function(p1_data) {
  return p2;
}).then(function(p2_data){
  return p3;
}).then(function(p3_data){
  return p4;
}).then(function(p4_data){
  // final result
}).catch(function(error){
  // 统一处理错误信息
});
24、在多个dom元素下遍历子元素,原生js实现,需要考虑什么
var _divArr = document.getElementsByClassName('area');
var divLength = _divArr.length;
for(var i = 0; 0 < divLength; i++){
      _divArr[i].className = 'othersName';
}

发现是隔行改变的,主要是由于每次操作这个dom元素的时候,原生js会自动再通过原来的查找条件再来查找一次,这里是通过document.getElementsByClassName('area')进行查找的,但是此时刚刚修改了classname的dom元素类名已经修改了,这样_divArr数组就发生了变化,其length也减小了,这样就导致每次修改的都是隔行数据,而且最后还会报js错误。

修改:将for循环中的i改为0

25、let 和 const

不存在变量提升,const不允许第二次赋值(对象属性除外)

26、class 类

(1)class设置私有方法

const bar = Symbol('bar');
const snaf = Symbol('sanf');

export default class myClass{
    //公有方法
    foo (baz) {
        this[bar] = baz;
    }
    
    // 私有方法
    [bar] (baz) {
        // 私有属性
        return this[scanf] = baz;
    }
    
}

(2)class设置私有属性
方法是在属性名之前,使用#表示

class Point {
    #x;
    
    constructor(x = 0) {
        #x = +x;  //写成this.#x也可以
    }
    
    get x() {
        return #x;
    }
    set x(value) {
        #x = +value;
    }
}
27、手写一个Dom树

node

1、Stream 和 Buffer 区别
2、event loop 原理
3、express

自express 4.x之后将许多中间件独立出来作为插件使用require的方式导入,非常符合unix哲学思想

一些常用插件:

body-parser
cookie-parser
express-session
http-proxy-middleware

非常有用的api

req.xhr():封装了判断请求是否为ajax请求的操作,相当于一个请求类型过滤器
req.json():返回一个json响应
res.render():渲染view,同时向callback传入渲染后的字符串
4、为什么事件驱动能构建高性能服务器

事件驱动的本质:通过主循环加事件触发的方式来运行程序

线程和进程的区别


html/css

1、repaint(重绘)和reflow(回流/重排)的区别

浏览器从下载文档到显示页面的过程包含了重绘和重排,由于浏览器的流布局,对渲染的计算通常只需要遍历一次就可以完成,但是table元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性

2、严格模式、怪异模式
3、缓存
4、FileReader实现图片上传

将图片读取为base64格式的字符串进行发送。而base64格式图片可以指定为图片src

let file = this.files[0];
let reader = new FileReader()
5、盒子模型
6、position: sticky
7、float塌陷怎么解决

安全

1、XSS攻击

XSS的本质是HTML注入,即用户输入的数据被当做HTML代码的一部分来执行,从而产生新的语义

类型:

常见的XSS有XSS PayloadXSS WOrm

2、CRSF
3、HTTPS
4、对称加密

网络相关

1、计算机网络

(1)MAC地址:即某站在网络中的物理地址,它由MAC帧进行传送。IEEE为每个站都规定了一个48位的全局地址,当一个站搬移到另一个局域网时,并不改变其全局地址。

(2)应用层,表示层,会话层:与应用问题相关;
传输层,网络层,数据链路层,物理层:主要处理网络控制和数据传输/接收问题

2、HTTP2有哪些新特性

http://blog.csdn.net/sugar_z_/article/details/51495792

3、HTTPS

http://www.cnblogs.com/zery/p/5164795.html

4、websocket

websocket是不同于HTTP的全双工通信协议,其显著特点在于服务器能主动推送消息给客户端,但是第一次连接还是由客户端发起的。事实上websocket是基于HTTP协议的,当三次握手的第一次握手结束后,服务器收到转换协议的upgrade:websocket字段,将协议再转换为websocket
成功建立连接后,通信不再使用HTTP数据帧,而是采用WebSocket独立的数据帧

websocket的用途:实现在线聊天室功能。客户端将数据信息发送到服务端,服务端经过处理后再将数据广播到客户端

5、socket.IO的解决点,什么时候用的到

socket.io 是基于node.js的,用于实时通信的websocket框架,主要分两个部分:
(1)运行在浏览器的客户端
(2)面向node.js的服务端
socket.io 底层是engine.io(websocket+XMLHttpRequest),这个库实现了跨平台双向通信

清理websocket连接验证:

6、TCP,UDP
1、TCP

(1)应用场景:文件传输
(2)TCP在数据包接收无序、丢失、或在交付期间被破坏时负责数据恢复

2、UDP

(1)应用场景:实时音视频(涉及网络穿透,不需要重传)
(2)UDP本身是面向非连接的无状态协议

3、TCP和UDP
7、三次握手,四次挥手

直白的讲解:http://blog.csdn.net/whuslei/article/details/6667471/

专有名词讲解:http://www.cnblogs.com/Jessy/p/3535612.html

8、浏览器缓存机制

https://mp.weixin.qq.com/s/qOMO0LIdA47j3RjhbCWUEQ

1、缓存存储策略

用于决定HTTP响应内容是否可以缓存到客户端

Cache-control:public/private/no-cache/max-age/[no-store] 前四个都会缓存文件(no-cahce 应理解为“不建议使用本地缓存”,其仍然会缓存数据到本地)。no-store不会在客户端存储任何响应数据

2、缓存过期策略

决定客户端是否可以直接从本地缓存数据中加载数据并展示(否则就发送请求到服务器获取)

Expires :指名缓存数据有效的绝对时间(时间点)

no-cachemax-age 既包含缓存存储策略也包含缓存过期策略

no-cachemax-age=0 相当,都是不缓存

max-age=10000 =

Cache-Control: public/private
Expires: 当前客户端时间+10000

Cache-Control 中指定的缓存过期策略优先级高于 Expires

3、缓存对比策略

将缓存在客户端的数据标识发往服务端,服务端通过标识来判断客户端缓存数据是否仍有效,进而决定是否要重发数据

浏览器检测到 数据过期浏览器刷新 ,通常会重发一个HTTP请求,此时服务器并不急着发送数据,而是首先检查标识 If-Modified-SinceIf-None-Match。如果判断标识仍有效,则返回304告诉客户端使用本地缓存即可

在没有设置缓存过期策略的情况下:`Expires = 当前时间 + (date - lastModified) * 10%

lastModified 是一个时间标识该资源最后修改的时间

9、cookie
1、对cookie的理解:
2、nodejs 创建cookie

服务端向客户端发送cookie;浏览器将cookie存储保存,之后每次浏览器都会将cookie发送到服务端

3、js 创建cookie
// 创建cookie
function addcookie (name, value, expireHours) {
    var cookieString = name + '=' + excape(value);  // escape 可对value进行编码,防止出现其他符号,取出cookie得使用unescape解码
    if (expireHours > 0) {
        var date = new Date();
        date.setTime(date.getTime + expireHours * 3600 * 1000);
        cookieString = cookieString + '; expire = ' + date.toGMTString();
    }
    // cookie 比较特殊,其他cookie不会被覆盖,而是同时存在,如要修改同名,则name为同名即可
    document.cookie = cookieString;
}

// 获取cookie
function getCookie (name) {
    var strcookie = document.cookie;
    var arrcookie = strcookie.split('; ');
    for (var i = 0; i < arrcookie.length; i++) {
        var arr = arrcookie[i].split('=');
        if (arr[0] == name) {
            return arr[1];
        }
    }
    return '';
}

// 删除cookie,通过过期时间删除
function deletecookie (name) {
    var date = new Date();
    date.setTime(date.getTime() - 10000);
    document.cookie = name + '=v; expire = ' + date.toGMTString();
}
4、cookie和webStorage区别
10、session
1、session作用
2、session和cookie的区别

算法和数据结构

1、九大排序算法
2、字典树
上一篇 下一篇

猜你喜欢

热点阅读