2019前端面试题及答案汇总

2019前端面试题及答案汇总

  • DOM事件流包含几个阶段
  • 事件委托(代理)的原理是什么?它有什么优势和缺点?
  • 使用原生JS为以下li实现事件委托,点击后打印对应的node-type属性值。
  • 使用jQuery为DOM元素绑定点击事件,有哪些方法?这些方法有什么区别?
  • null和undefined区别
  • 什么是原型链?什么是作用域链?分别有什么作用?
  • 请写出以下这段JS代码的输出结果,并解释原因。
  • 请写出以下这段JS代码的输出结果,并解释原因。
  • 请写出以下这段JS代码的输出结果,并解释原因。
  • 什么是函数节流,有什么作用?请写一段函数节流的示范代码
  • JS基础数据类型与引用数据类型分别有哪些?请根据提示完成以下getType函数代码。
  • 已知构造函数A,请实现B函数,需要继承A
  • New操作符具体干了什么
  • 如何准确的判断一个变量是否为数组
  • 数组去重方法
  • 输出结果
  • 输出结果
  • 同步和异步的区别
  • 进程与线程
  • 对象的深拷贝实现方法
  • 浏览器输入URL到页面显示在用户面前,这个过程发生了什么
  • 网络传输共几层
  • TCP/IP网络协议分几层
  • HTTPS和HTTP的区别

DOM事件流包含几个阶段

事件捕获阶段、处于目标阶段、事件冒泡阶段

事件委托(代理)的原理是什么?它有什么优势和缺点?

原理:事件委托的原理是事件冒泡。

优势:减少事件注册,大量降低内存消耗;对于新增子元素不需要重新绑定事件,对动态DOM尤其适用。

缺点:容易产生事件误判,即给不需要触发事件的元素绑定了事件

使用原生JS为以下li实现事件委托,点击后打印对应的node-type属性值。

var oUl = document.getElementById('test');
oUl.addEventListener('click', function(e){
     var ev = e || window.event;
     var target = ev.target || ev.srcElement;
     if(target.nodeName == 'LI'){
       console.log(target.getAttribute('node-type'))
     }
 },true)

使用jQuery为DOM元素绑定点击事件,有哪些方法?这些方法有什么区别?

jQuery中事件绑定有四种方式:on、bind、live和delegate。

  1. on 推荐使用
    on(events,[selector],[data],fn)
    在选择元素上绑定一个或多个事件的事件处理函数
$("#clickme").on("click",function(){
 console.log("clicked");
})
  1. bind
    bind(type,[data],fn)
    为每个匹配元素的特定事件绑定事件处理函数,只能绑定既有元素
$("#clickme").bind("click",function(){
	console.log("clicked");
});
  1. live
    live(type,[data],fn)
    给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的
$("#clickme").live("click",function(){
	console.log("clicked");
})
  1. delegate
    delegate(selector,[type],[data],fn)
    指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数
$("#clickme").delegate("a","click",function(){
    console.log("clicked");
})
  1. 还有一种简写方式
$("#clickme").click(function(){
	console.log("clicked");
})
  1. 如果事件只调用一次可使用one()方法
$("#clickme").one('click',function(){
	console.log("clicked");
})

null和undefined区别

  1. 类型不同

    null表示一个空对象指针,类型为object;
    undefined表示未被初始化的变量(声明的变量没有被赋值),类型为undefined。

  2. 转换为数值返回值不同

    null 转换为数值类型结果为0;
    undefined转化为数值型返回NaN。

  3. 二者不完全相等

 null == undefined  //true
 null === undefined  //false

什么是原型链?什么是作用域链?分别有什么作用?

原型链是针对构造函数的。
如我先创建了一个函数A,然后通过new A()创建了函数B,此时B就会继承A的属性和方法。示例如下,当我访问B函数的name属性时,发现B中并没有声明这个属性,那么就会向上查找,在A中发现了name属性并返回,这个向上查找的过程叫做原型链。
Object——>A()——>B()

function A(){
	this.name = "Amy",
	this.age = 1
}
var B = new A()
console.log(B.name);

作用域链是针对变量的。
当A函数中声明了B函数,访问B函数的某个变量未被找到,就会向A函数中查找,这个向上查找的过程叫做作用域链。作用域链是由内向外逐层产生的且不可逆,一直会找到全局作用域。

var a = 1;
function A(){
    var a = 2;
    function B(){
        console.log(a);
    }
    c();
}
B();	//2

请写出以下这段JS代码的输出结果,并解释原因。

var num = 100;
var obj = {
    num:200,
    inner:{
        num:300,
        print:function(){
            console.log(this.num);
        }
    }
}
obj.inner.print();		//300
var func=obj.inner.print;
func();		//100
(obj.inner.print)();		//300
(obj.inner.print=obj.inner.print())()	//300

请写出以下这段JS代码的输出结果,并解释原因。

var num = 100;
function print(){
    console.log(num);
    var num;
}
print();		//undefined
函数作用域内num变量声明被提升,但是未被初始化所以返回undefined。

请写出以下这段JS代码的输出结果,并解释原因。

(function(num){
    console.log(num);
    var num = 10;
})(100)		//100

什么是函数节流,有什么作用?请写一段函数节流的示范代码

函数被频繁的调用会对性能造成大的影响,函数节流即利用定时器控制函数不被频繁调用。
如window.onresize事件、mousemove事件

window.onresize = function throttle(){
	var timer = null;
	clear(timer);
	timer = setTimeOut(function(){
		console.log(123);
	},100)
}

JS基础数据类型与引用数据类型分别有哪些?请根据提示完成以下getType函数代码。

基础数据类型:null、undefined、number、boolean、string、symbol
引用数据类型:object、function

/**
 * 返回变量的具体类型名称
 * @param obj 待判断的变量
 */
function getType(obj){
	var typeName = Object.prototype.toString.call(obj);
 	if( typeName == "[object Object]"){
      return typeName = obj.constructor.name;
   }else{
	return typeName.slice(8,-1);
   }
}

已知构造函数A,请实现B函数,需要继承A

var A=function(name){
    this.username=name;
}

A.prototype={
    fun1:function(){},
    fun2:function(){}
}

var B = new A();

New操作符具体干了什么

对于const a = new Foo();,new干了以下事情

const o = new Object();//创建了一个新的空对象o
o.__proto__ = Foo.prototype;//让这个o对象的` __proto__`指向函数的原型`prototype`
Foo.call(o);//this指向o对象
a = o;//将o对象赋给a对象

如何准确的判断一个变量是否为数组

1.instanceof 判断一个对象是否是由某个类型创建出来的

obj instanceof Array = true   //则表示是数组

2.Object.prototype.toString()方法

Object.prototype.toString.call(arr)   == [object Array]

3.Array.prototype.isPrototypeOf(obj) //判断指定对象是否存在于另一对象的原型链中

Array.prototype.isPrototypeOf(obj)  == true

4.Obejct.getPrototypeOf(arr) == Array.prototype

Object.getPrototypeOf(arr)== Array.prototype  //返回对象__proto__指向的原型prototype 

5.最简单的方法(存在兼容)

Array.isArray(arr) ==  true

数组去重方法

  1. Array.filter() + indexOf

这个方法的思路是,使用 ES6 中的 Array.filter() 遍历数组,并结合 indexOf 来排除重复项

function distinct(arr) {
    return arr.filter((item, index)=> {
        return arr.indexOf(item) === index
    })
}

  1. 双重 for 循环(不推荐)

最容易理解的方法,外层循环遍历元素,内层循环检查是否重复,当有重复值的时候,可以使用 push(),也可以使用 splice()

function distinct(arr) {
    for (let i=0, len=arr.length; i
  1. for…of + includes()

双重for循环的升级版,外层用 for…of 语句替换 for 循环,把内层循环改为 includes()。先创建一个空数组,当 includes() 返回 false 的时候,就将该元素 push 到空数组中。类似的,还可以用 indexOf() 来替代 includes()

function distinct(arr) {
    let arr = a.concat(b)
    let result = []
    for (let i of arr) {
        !result.includes(i) && result.push(i)
    }
    return result
}
  1. Array.sort()

首先使用 sort() 将数组进行排序,然后比较相邻元素是否相等,从而排除重复项。

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
  1. new Set()(推荐,简洁效率高)

ES6 新增了 Set 这一数据结构,类似于数组,但 Set 的成员具有唯一性,基于这一特性,就非常适合用来做数组去重了

function distinct(arr) {
    return Array.from(new Set([...arr]))
}

  1. for…of + Object(效率最优)

首先创建一个空对象,然后用 for 循环遍历,利用对象的属性不会重复这一特性,校验数组元素是否重复。

function distinct(arr) {
    let result = []
    let obj = {}

    for (let i of arr) {
        if (!obj[i]) {
            result.push(i)
            obj[i] = 1
        }
    }

    return result
}
  1. for循环+indexOf去重
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}

输出结果

var a = 10;
a.pro = 10;
console.log(a.pro + a);	//NaN

var s = "hello";
s.pro = "world";
console.log(s.pro + s)		//undefinedhello

输出结果

var test = 1;
function test(index){
    console.log(index);
    index = 3;
}
test(2);		//报错  类型错误,test不是一个函数

同步和异步的区别

同步就是上一件事情没有完成,继续处理上一件事情,只有上一件事情完成了,才会做下一件事情。JS中大部分都是同步编程。

异步规划要做一件事情,但是不是当前立马去执行这件事情,需要等一定的时间,这样的话,我们不会等着他执行,而是继续执行下面的操作,只有当下面的事情都处理完成了,才会返回头处理之前的事情;如果下面的事情并没有处理完成,不管之前的事情有没有到时间,都需要等待”。

在JS中,异步编程只有四种情况:

  1. 定时器都是异步编程的
  2. 所有的事件绑定都是异步编程的
  3. Ajax读取数据都是异步编程的,我们一般设置为异步编程
  4. 回调函数都是异步编程的

进程与线程

进程代表CPU所能处理的单个任务。任一时刻,CPU只能处理一个进程。
一个进程可以包含多个线程

对象的深拷贝实现方法

  1. 赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;
  2. JavaScript 中数组(concat、slice)和对象(assign、展开运算符… 、)自带的拷贝方法都是“首层浅拷贝”;
  3. JSON.stringify 实现的是深拷贝,但是对目标对象有要求(非 undefined,function,symbol。当值为undefined、function、symbol 会在转换过程中被忽略。。。);
var syb = Symbol('obj');
var person = {
   name :'tino',
   say: function(){
      console.log('hi');
   },
   ok: syb,
   un: undefined
}
var copy = JSON.parse(JSON.stringify(person))
// copy
// {name: "tino"}
  1. 若想真正意义上的深拷贝,请递归。
function deepCopy(obj) {
      var result = Array.isArray(obj) ? [] : {};
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (typeof obj[key] === 'object' && obj[key]!==null) {
            result[key] = deepCopy(obj[key]);   //递归复制
          } else {
            result[key] = obj[key];
          }
        }
      }
      return result;
    }

浏览器输入URL到页面显示在用户面前,这个过程发生了什么

1、域名解析

域名解析的过程:

	1).查询浏览器自身DNS缓存
	
    2).若上面没有查找到,则搜索操作系统自身的dns缓存

    3).若上面没有找到,则尝试读取hosts文件

    4).若上面没有找到,向本地配置的首选DNS服务器发送请求

    5).win系统 如果上面没有找到,操作系统查找NetBIOS name cache

    6).win系统 如果上面没有找到,查询wins服务器

    7).win系统 如果上面没有找到,广播查找

    8).win系统 如果上面没有找到,读取LMHOSTS文件

若以上多没有找到,解析失败

2、 TCP三次握手

3、浏览器向服务器发送http请求

一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令。

4、浏览器发送请求头信息

浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。

5、服务器处理请求

服务器软件收到http请求,确定执行什么(ASP.net PHP RUBY JAVA等)来处理他。读取参数并进行逻辑操作后,生成指定的数据。

6、服务器做出应答

客户机向服务器发出请求后,服务器会客户机回送应答,HTTP/1.1 200 OK ,应答的第一部分是协议的版本号和应答状态吗

7、服务器发送应答头信息

正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。

8、服务器发送数据

Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。

9、TCP连接关闭

一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

网络传输共几层

1、物 理 层(Physical Layer)
要传递信息就要利用一些物理媒体,如双纽线、同轴电缆等,但具体的物理媒体并不在OSI的7层之内,有人把物理媒体当作第0层,物理层的任务就是为它的上一层提供一个物理连接,以及它们的机械、电气、功能和过程特性。 如规定使用电缆和接头的类型,传送信号的电压等。在这一层,数据还没有被组织,仅作为原始的位流或电气电压处理,单位是比特。
2、 数 据 链 路 层(Data Link Layer)
数据链路层负责在两个相邻结点间的线路上,无差错的传送以帧为单位的数据。每一帧包括一定数量的数据和一些必要的控制信息。和物理层相似,数据链路层要负责建立、维持和释放数据链路的连接。在传送数据时,如果接收点检测到所传数据中有差错,就要通知发方重发这一帧。
3、 网 络 层(Network Layer)
在计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。网络层将数据链路层提供的帧组成数据包,包中封装有网络层包头,其中含有逻辑地址信息- -源站点和目的站点地址的网络地址。
4、 传 输 层(Transport Layer)
该层的任务时根据通信子网的特性最佳的利用网络资源,并以可靠和经济的方式,为两个端系统(也就是源站和目的站)的会话层之间,提供建立、维护和取消传输连接的功能,负责可靠地传输数据。在这一层,信息的传送单位是报文。
5、 会 话 层(Session Layer)
这一层也可以称为会晤层或对话层,在会话层及以上的高层次中,数据传送的单位不再另外命名,统称为报文。会话层不参与具体的传输,它提供包括访问验证和会话管理在内的建立和维护应用之间通信的机制。如服务器验证用户登录便是由会话层完成的。
6、 表 示 层(Presentation Layer)
这一层主要解决拥护信息的语法表示问题。它将欲交换的数据从适合于某一用户的抽象语法,转换为适合于OSI系统内部使用的传送语法。即提供格式化的表示和转换数据服务。数据的压缩和解压缩, 加密和解密等工作都由表示层负责。
7、 应 用 层(Application Layer)
应用层确定进程之间通信的性质以满足用户需要以及提供网络与用户应用软件之间的接口服务。
上面我们简单的说明了7层体系的OSI参考模型,为了方便起见,我们常常把上面的7个层次分为低层与高层。低层为1-4层,是面向通信的,高层为5~7层,是面向信息处理的。

TCP/IP网络协议分几层

4层,自底向上依次为网络接口层、网络层、传输层和应用层。
TCP特点:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

HTTPS和HTTP的区别

主要为以下四点:

  1. https协议需要到ca申请证书,一般免费证书很少,需要交费。
  2. http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

你可能感兴趣的:(JavaScript)