2019前端面试题 | JS部分(附带答案)

目前在找工做,因此各方收集了一堆面试题。其实刷面试题的过程也能更新本身对知识的认识,因此也提醒本身多看多理解。若是对下面题目有更深理解,会实时更新。遇到新题目,也会不定时更新。但愿能帮助到部分朋友~javascript

1、各类函数方法定义及区别

1. typeof运算符和instanceof运算符以及isPrototypeOf()方法的区别

typeof是一个运算符,用于检测数据的类型,好比基本数据类型null、undefined、string、number、boolean,以及引用数据类型object、function,可是对于正则表达式、日期、数组这些引用数据类型,它会所有识别为object; instanceof一样也是一个运算符,它就能很好识别数据具体是哪种引用类型。它与isPrototypeOf的区别就是它是用来检测构造函数的原型是否存在于指定对象的原型链当中;而isPrototypeOf是用来检测调用此方法的对象是否存在于指定对象的原型链中,因此本质上就是检测目标不一样。html

2.call()和apply()的区别

实际上,apply和call的功能是同样的,只是传入的参数列表形式不一样。apply:最多只能有两个参数——新this对象和一个数组argArray。java

参考:www.cnblogs.com/lengyuehuah…面试

3.全局函数eval()有什么做用?

eval()只有一个参数,若是传入的参数不是字符串,它直接返回这个参数。若是参数是字符串,它会把字符串当成javascript代码进行编译。若是编译失败则抛出一个语法错误(syntaxError)异常。若是编译成功,则开始执行这段代码,并返回字符串中的最后一个表达式或语句的值,若是最后一个表达式或语句没有值,则最终返回undefined。若是字符串抛出一个异常,这个异常将把该调用传递给eval()。ajax

4.描述如下变量的区别:null,undefined或undeclared

null 表示"没有对象",即该处不该该有值,转为数值时为0。典型用法是:正则表达式

(1) 做为函数的参数,表示该函数的参数不是对象。json

(2) 做为对象原型链的终点。小程序

undefined 表示"缺乏值",就是此处应该有一个值,可是尚未定义,转为数值时为NaN。典型用法是:跨域

(1)变量被声明了,但没有赋值时,就等于undefined。数组

(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。

(3)对象没有赋值的属性,该属性的值为undefined。

(4)函数没有返回值时,默认返回undefined。

undeclared :js语法错误,没有申明直接使用,js没法找到对应的上下文。

5.==和===有什么区别?

首先,== equality 等同,=== identity 恒等。==,两边值类型不一样的时候,要先进行类型转换,再比较。===,不作类型转换,类型不一样的必定不等。

先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等:

若是类型不一样,就[不相等] 
若是两个都是数值,而且是同一个值,那么[相等];(!例外)的是,若是其中至少一个是NaN,那么[不相等]。(判断一个值是不是NaN,只能用isNaN()来判断) 
若是两个都是字符串,每一个位置的字符都同样,那么[相等];不然[不相等]。 
若是两个值都是true,或者都是false,那么[相等]。 
若是两个值都引用同一个对象或函数,那么[相等];不然[不相等]。 
若是两个值都是null,或者都是undefined,那么[相等]。 
复制代码

再说 ==,根据如下规则: 若是两个值类型相同,进行 === 比较。 若是两个值类型不一样,他们可能相等。根据下面规则进行类型转换再比较:

若是一个是null、一个是undefined,那么[相等]。 
若是一个是字符串,一个是数值,把字符串转换成数值再进行比较。 
若是任一值是 true,把它转换成 1 再比较;若是任一值是 false,把它转换成 0 再比较。 
若是一个是对象,另外一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的
toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂) 
任何其余组合,都[不相等]。
复制代码

6.同步异步?

一、进程同步:就是在发出一个功能调用时,在没有获得结果以前,该调用就不返回。也就是必须一件一件事作,等前一件作完了才能作下一件事 二、异步的概念和同步相对。当一个异步过程调用发出后,调用者不能马上获得结果。实际处理这个调用的部件在完成后,经过状态、通知和回调来通知调用者。

2、各类概念/原理

1. 什么是事件代理/事件委托?

事件代理/事件委托是利用事件冒泡的特性,将本应该绑定在多个元素上的事件绑定在他们的祖先元素上,尤为在动态添加子元素的时候,能够很是方便的提升程序性能,减少内存空间。

2.什么是事件冒泡?什么是事件捕获?

冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

捕获型事件:事件从最不精确的对象(document 对象)开始触发,而后到最精确(也能够在窗口级别捕获事件,不过必须由开发人员特别指定)。

支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,仍是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,因此把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。

3.如何阻止冒泡?

w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true。例如: window.event? window.event.cancelBubble = true : e.stopPropagation();

return false也能够阻止冒泡。

4.如何阻止默认事件?

w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false,好比:

function stopDefault( e ) { 
    //阻止默认浏览器动做(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函数器默认动做的方式 
    else 
        window.event.returnValue = false; 
}
复制代码

return false也能阻止默认行为。

5.简述javascript中this的指向

第一准则是:this永远指向函数运行时所在的对象,而不是函数被建立时所在的对象。

  • 普通的函数调用,函数被谁调用,this就是谁。
  • 构造函数的话,若是不用new操做符而直接调用,那即this指向window。用new操做符生成对象实例后,this就指向了新生成的对象。
  • 匿名函数或不处于任何对象中的函数指向window 。
  • 若是是call,apply等,指定的this是谁,就是谁。
  • 参考:www.cnblogs.com/beidan/p/53…

5.原生对象和宿主对象

原生对象是ECMAScript规定的对象,全部内置对象都是原生对象,好比Array、Date、RegExp等;

宿主对象是宿主环境好比浏览器规定的对象,用于完善是ECMAScript的执行环境,好比Document、Location、Navigator等。

6.基本数据类型和引用数据类型

基本数据类型指的是简单的数据段,有5种,包括null、undefined、string、boolean、number;

引用数据类型指的是有多个值构成的对象,包括object、array、date、regexp、function等。

主要区别:

  • 声明变量时不一样的内存分配:前者因为占据的空间大小固定且较小,会被存储在栈当中,也就是变量访问的位置;后者则存储在堆当中,变量访问的实际上是一个指针,它指向存储对象的内存地址。
  • 也正是由于内存分配不一样,在复制变量时也不同。前者复制后2个变量是独立的,由于是把值拷贝了一份;后者则是复制了一个指针,2个变量指向的值是该指针所指向的内容,一旦一方修改,另外一方也会受到影响。
  • 参数传递不一样:虽然函数的参数都是按值传递的,可是引用值传递的值是一个内存地址,实参和形参指向的是同一个对象,因此函数内部对这个参数的修改会体如今外部。原始值只是把变量里的值传递给参数,以后参数和这个变量互不影响。

7.深拷贝和浅拷贝

区别 www.cnblogs.com/echolun/p/7…

深拷贝的方法 www.cnblogs.com/Mrrabbit/p/…

8.解释一下原型继承的原理

参考:www.cnblogs.com/syfwhu/p/44…

9.解释下为何接下来这段代码不是IIFE(当即调用的函数表达式):

function foo(){
    //code
}()
复制代码

以function关键字开头的语句会被解析为函数声明,而函数声明是不容许直接运行的。 只有当解析器把这句话解析为函数表达式,才可以直接运行,怎么办呢?以运算符开头就能够了。

(function foo(){
    // code..
})()
复制代码

10.请尽量详尽的解释AJAX的工做原理

ajax简单来讲是经过XmlHttpRequest对象来向服务器发异步请求,从服务器得到数据,而后用javascript来操做DOM而更新页面。

ajax的优势

  • 最大的一点是页面无刷新,在页面内与服务器通讯,给用户的体验很是好。
  • 使用异步方式与服务器通讯,不须要打断用户的操做,具备更加迅速的响应能力。
  • 能够把之前一些服务器负担的工做转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本,ajax的原则是“按需取数据”,能够最大程度的减小冗余请求。
  • 基于标准化的并被普遍支持的技术,不须要下载插件或者小程序。

ajax的缺点

  • ajax对浏览器后退机制形成了破坏,也就是说用户没法经过浏览器的后退按钮回到前一次操做的页面。虽然有些浏览器解决了这个问题,好比Gmail,但它也并不能改变ajax的机制,它所带来的开发成本是很是高的,和ajax框架所要求的快速开发是相背离的。这是ajax所带来的一个很是严重的问题。
  • 安全问题。技术同时也对IT企业带来了新的安全威胁,ajax技术就如同对企业数据创建了一个直接通道。这使得开发者在不经意间会暴露比之前更多的数据和服务器逻辑。
  • 对搜索引擎的支持比较弱。
  • 破坏了程序的异常机制。至少从目前看来,像ajax.dll,ajaxpro.dll这些ajax框架是会破坏程序的异常机制的。关于这个问题,我曾经在开发过程当中遇到过,可是查了一下网上几乎没有相关的介绍。后来我本身作了一次试验,分别采用ajax和传统的form提交的模式来删除一条数据……给咱们的调试带来了很大的困难。
  • 另外,像其余方面的一些问题,好比说违背了url和资源定位的初衷。例如,我给你一个url地址,若是采用了ajax技术,也许你在该url地址下面看到的和我在这个url地址下看到的内容是不一样的。这个和资源定位的初衷是相背离的。
  • 一些手持设备(如手机、PDA等)如今还不能很好的支持ajax,好比说咱们在手机的浏览器上打开采用ajax技术的网站时,它目前是不支持的,固然,这个问题和咱们没太多关系。

11.get和post有什么区别?

其实,GET和POST本质上二者没有任何区别。他们都是HTTP协议中的请求方法。底层实现都是基于TCP/IP协议。所谓区别,只是浏览器厂家根据约定,作得限制而已。

  • get是经过明文发送数据请求,而post是经过密文;
  • get传输的数据量有限,由于url的长度有限,post则不受限;
  • GET请求的参数只能是ASCII码,因此中文须要URL编码,而POST请求传参没有这个限制
  • GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
  • 参考:www.cnblogs.com/logsharing/…

12.请解释变量声明提高

经过var声明的变量会被提高至做用域的顶端。不只仅是变量,函数声明也同样会被提高。当同一做用域内同时出现变量和函数声明提高时,变量仍然在函数前面。

参考:www.cnblogs.com/guanhuachen…

13.请指出document.onload和document.ready两个事件的区别

页面加载完成有两种事件,一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件),二是onload,指示页面包含图片等文件在内的全部元素都加载完成。

14.如何从浏览器的URL中获取查询字符串参数?

getUrlParam : function(name){
        //baidu.com/product/list?keyword=XXX&page=1
        var reg     = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
        var result  = window.location.search.substr(1).match(reg);
        return result ? decodeURIComponent(result[2]) : null;
    }
复制代码

  • 首先设置一个函数,给这个函数传递一个参数,也就是url的search部分的key值;
  • 设置一个正则表达式,以&开头或没有,中间是参数,后面以#或&结尾或没有;
  • 经过window.location.search.substr(1).match()匹配,返回一个数组
  • 若是数组不为空,返回数组的第3个值,也就是正则表达式的第二个子串

15.什么是三元表达式?“三元”表示什么意思?

三元表达式:? :。三元--三个操做对象。

在表达式boolean-exp ? value0 : value1 中,若是“布尔表达式”的结果为true,就计算“value0”,并且这个计算结果也就是操做符最终产生的值。若是“布尔表达式”的结果为false,就计算“value1”,一样,它的结果也就成为了操做符最终产生的值。

16.JavaScript里arguments到底是什么?

Javascrip中国每一个函数都会有一个Arguments对象实例arguments,它引用着函数的实参,能够用数组下标的方式"[]"引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。

在函数代码中,使用特殊对象arguments,开发者无需明确指出参数名,经过使用下标就能够访问相应的参数。

function test() {
        var s = "";
        for (var i = 0; i < arguments.length; i++) {
            alert(arguments[i]);
            s += arguments[i] + ",";
        }
        return s;
    }
    test("name", "age");//name,age
复制代码

arguments虽然有一些数组的性质,但其并不是真正的数组,只是一个类数组对象。其并无数组的不少方法,不能像真正的数组那样调用.jion(),.concat(),.pop()等方法。

17.什么是"use strict";?使用它的好处和坏处分别是什么?

在代码中出现表达式-"use strict"; 意味着代码按照严格模式解析,这种模式使得Javascript在更严格的条件下运行。

好处:

  • 消除Javascript语法的一些不合理、不严谨之处,减小一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提升编译器效率,增长运行速度;
  • 为将来新版本的Javascript作好铺垫。

坏处:

  • 一样的代码,在"严格模式"中,可能会有不同的运行结果;
  • 一些在"正常模式"下能够运行的语句,在"严格模式"下将不能运行。

18.请解释一下JavaScript的同源策略

同源策略,即拥有相同的协议(protocol),端口(若是指定),主机(域名)的两个页面是属于同一个源。 然而在IE中比较特殊,IE中没有将端口号加入同源的条件中,所以上图中端口不一样那一项,在IE中是算同源的。 <script> <img> <iframe>中的src,href均可以任意连接网络资源,是不遵循通源策略的。

19.请解释JSONP的工做原理,以及它为何不是真正的AJAX。

JSONP (JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签能够加载并执行其余域的javascript,因而咱们能够经过script标记来动态加载其余域的资源。例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA须要的数据,而后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完以后会执行pageA中定义的函数,所须要的数据会以参数的形式传递给该函数。JSONP易于实现,可是也会存在一些安全隐患,若是第三方的脚本随意地执行,那么它就能够篡改页面内容,截获敏感数据。可是在受信任的双方传递数据,JSONP是很是合适的选择。

AJAX是不跨域的,而JSONP是一个是跨域的,还有就是两者接收参数形式不同!

20.经过new建立一个对象的时候,构造函数内部有哪些改变?

function Person(){}
Person.prototype.friend = [];
Person.prototype.name = '';
var a = new Person();
a.friend[0] = '王琦';
var b = new Person();
console.log(b.friend);//Array [ "王琦" ]
复制代码
  • 建立一个空对象,而且 this 变量引用该对象,同时还继承了该函数的原型。
  • 属性和方法被加入到 this 引用的对象中。
  • 新建立的对象由 this 所引用,而且最后隐式的返回 this 。

22.什么是跨域?有什么方法解决跨域带来的问题?

跨域须要针对浏览器的同源策略来理解,同源策略指的是请求必须是同一个端口,同一个协议,同一个域名,不一样源的客户端脚本在没有明确受权的状况下,不能读写对方资源。

受浏览器同源策略的影响,不是同源的脚本不能操做其余源下面的对象。想要操做另外一个源下的对象是就须要跨域。

解决方法: jsonp

23. 什么是原型?

原型链:简单来说就是原型组成的链,好比函数的原型是Function,Function的原型是Object,Object的原型仍然是Object,一直追溯到最终的原型对象。

函数经过prototype来追溯原型对象,对象经过_proto_来追溯原型对象。

经过一个构造函数建立出来的多个实例,若是都要添加一个方法,给每一个实例去添加并非一个明智的选择。这时就该用上原型了。

在实例的原型上添加一个方法,这个原型的全部实例便都有了这个方法。

原型链继承:

function Show(){
this.name="run";
}

function Run(){
this.age="20"; //Run继承了Show,经过原型,造成链条
}
Run.prototype=new Show();
var show=new Run();
alert(show.name)//结果:run
复制代码

24. 什么是闭包?使用场景是?

闭包就是可以读取其余函数内部变量的函数,一般是函数嵌套时产生,它的最大用处有两个,一个是能够读取函数内部的变量,另外一个就是让这些变量的值始终保持在内存中,不会在外部函数调用后被自动清除。

25. 了解过Promise吗?与回调地狱有什么关系?

www.liaoxuefeng.com/wiki/001434…

3、关于定时器的那些事儿~(偏小白逻辑)

1.若是用户持续点击一个按钮,如何只提交一次请求,且不影响后续使用?(其实就是如何节流这个真的问的好多!!!!)

何为节流 触发函数事件后,短期间隔内没法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用,通常用于http请求。

解决原理 对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。

function conso(){
          console.log('is run');
      }
      var btnUse=true;
     $("#btn").click(function(){
         if(btnUse){
             conso();
             btnUse=false;
         }
         setTimeout(function(){
             btnUse=true;
         },1500) //点击后相隔多长时间可执行
     })
复制代码

2.如何防抖?(通常都和节流一块儿问,必定要搞懂!!)

何为防抖 屡次触发事件后,事件处理函数只执行一次,而且是在触发操做结束时执行,通常用于scroll事件。

解决原理 对处理函数进行延时操做,若设定的延时到来以前再次触发事件,则清除上一次的延时操做定时器,从新定时。

let timer;
window.onscroll  = function () {
    if(timer){
        clearTimeout(timer)
    }
    timer = setTimeout(function () {
        //滚动条位置
        let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置:' + scrollTop);
        timer = undefined;
    },200)
}
复制代码

或者是这样:

function debounce(fn, wait) {
    var timeout = null;
    return function() {  
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}
// 处理函数
function handle() {    
    console.log(Math.random()); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
复制代码

2.猜猜以下题目的结果?

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  setInterval(() => this.s1++, 1000);
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
复制代码

答案是:

s1: 3
s2: 0
复制代码
相关文章
相关标签/搜索