前端基础面试题(JS部分)
1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构?javascript
基本数据类型:Undefined、Null、Boolean、Number、String
值类型:数值、布尔值、null、undefined。
引用类型:对象、数组、函数。
堆栈数据结构:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出!
js数组中提供了如下几个方法可让咱们很方便实现堆栈:
shift:从数组中把第一个元素删除,并返回这个元素的值。
unshift: 在数组的开头添加一个或更多元素,并返回新的长度
push:在数组的中末尾添加元素,并返回新的长度
pop:从数组中把最后一个元素删除,并返回这个元素的值。php
2.声明函数做用提高?声明变量和声明函数的提高有什么区别?css
(1) 变量声明提高:变量申明在进入执行上下文就完成了。
只要变量在代码中进行了声明,不管它在哪一个位置上进行声明, js引擎都会将它的声明放在范围做用域的顶部;html(2) 函数声明提高:执行代码以前会先读取函数声明,意味着能够把函数申明放在调用它的语句后面。
只要函数在代码中进行了声明,不管它在哪一个位置上进行声明, js引擎都会将它的声明放在范围做用域的顶部;前端(3) 变量or函数声明:函数声明会覆盖变量声明,但不会覆盖变量赋值。
同一个名称标识a,即有变量声明var a,又有函数声明function a() {},无论两者声明的顺序,函数声明会覆盖变量声明,也就是说,此时a的值是声明的函数function a() {}。注意:若是在变量声明的同时初始化a,或是以后对a进行赋值,此时a的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a);java
3.判断数据类型?node
typeof返回的类型都是字符串形式,能够判断function的类型;在判断除Object类型的对象时比较方便。
判断已知对象类型的方法: instanceof,后面必定要是对象类型,而且大小写不能错,该方法适合一些条件选择或分支。jquery
4.异步编程?webpack
方法1:回调函数,优势是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,并且每一个任务只能指定一个回调函数。git
方法2:时间监听,能够绑定多个事件,每一个事件能够指定多个回调函数,并且能够“去耦合”(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
方法3:发布/订阅,性质与“事件监听”相似,可是明显优于后者。
方法4:Promises对象,是CommonJS工做组提出的一种规范,目的是为异步编程提供统一接口。
简单说,它的思想是,每个异步任务返回一个Promise对象,该对象有一个then方法,容许指定回调函数。
5.事件流?事件捕获?事件冒泡?
事件流:从页面中接收事件的顺序。也就是说当一个事件产生时,这个事件的传播过程,就是事件流。
IE中的事件流叫事件冒泡;事件冒泡:事件开始时由最具体的元素接收,而后逐级向上传播到较为不具体的节点(文档)。对于html来讲,就是当一个元素产生了一个事件,它会把这个事件传递给它的父元素,父元素接收到了以后,还要继续传递给它的上一级元素,就这样一直传播到document对象(亲测如今的浏览器到window对象,只有IE8及下不这样
事件捕获是不太具体的元素应该更早接受到事件,而最具体的节点应该最后接收到事件。他们的用意是在事件到达目标以前就捕获它;也就是跟冒泡的过程正好相反,以html的click事件为例,document对象(DOM级规范要求从document开始传播,可是如今的浏览器是从window对象开始的)最早接收到click事件的而后事件沿着DOM树依次向下传播,一直传播到事件的实际目标;
6.如何清除一个定时器?
window.clearInterval();
window.clearTimeout();
7.如何添加一个dom对象到body中?innerHTML和innerText区别?
body.appendChild(dom元素);
innerHTML:从对象的起始位置到终止位置的所有内容,包括Html标签。
innerText:从起始位置到终止位置的内容, 但它去除Html标签
分别简述五个window对象、属性成员对象
window.event window.document window.history
window.screen window.navigator window.external
Window对象的属性以下:
window //窗户自身
window.self //引用本窗户window=window.self
window.name //为窗户命名
window.defaultStatus //设定窗户状态栏信息
window.location //URL地址,配备布置这个属性能够打开新的页面
8.数据持久化技术(ajax)?简述ajax流程
1)客户端产生js的事件
2)建立XMLHttpRequest对象
3)对XMLHttpRequest进行配置
4)经过AJAX引擎发送异步请求
5)服务器端接收请求而且处理请求,返回html或者xml内容
6)XML调用一个callback()处理响应回来的内容
7)页面局部刷新
9.回调函数?
回调函数就是一个经过函数指针调用的函数。若是你把函数的指针(地址)做为参数传递给另外一个函数,当这个指针被用来调用其所指向的函数时,咱们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
10.什么是闭包? 堆栈溢出有什么区别? 内存泄漏? 那些操做会形成内存泄漏?怎么样防止内存泄漏?*
闭包:就是可以读取其余函数内部变量的函数。
堆栈溢出:就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,致使数据越界,结果覆盖了别的数据。常常会在递归中发生。
内存泄露是指:用动态存储分配函数内存空间,在使用完毕后未释放,致使一直占据该内存单元。直到程序结束。指任何对象在您再也不拥有或须要它以后仍然存在。形成内存泄漏:
setTimeout 的第一个参数使用字符串而非函数的话,会引起内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
防止内存泄露:
一、不要动态绑定事件;
二、不要在动态添加,或者会被动态移除的dom上绑事件,用事件冒泡在父容器监听事件;
三、若是要违反上面的原则,必须提供destroy方法,保证移除dom后事件也被移除,这点能够参考Backbone的源代码,作的比较好;
四、单例化,少建立dom,少绑事件。
11.平时工做中怎么样进行数据交互?若是后台没有提供数据怎么样进行开发?mock数据与后台返回的格式不一样意怎么办?
由后台编写接口文档、提供数据接口实、前台经过ajax访问实现数据交互;
在没有数据的状况下寻找后台提供静态数据或者本身定义mock数据;
返回数据不统一时编写映射文件 对数据进行映射。
12 简述ajax执行流程
基本步骤:
var xhr =null;//建立对象 if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open(“方式”,”地址”,”标志位”);//初始化请求 xhr.setRequestHeader(“”,””);//设置http头信息 xhr.onreadystatechange =function(){}//指定回调函数 xhr.send();//发送请求
13.自执行函数?用于什么场景?好处?
自执行函数:一、声明一个匿名函数二、立刻调用这个匿名函数。
做用:建立一个独立的做用域。好处:防止变量弥散到全局,以避免各类js库冲突。隔离做用域避免污染,或者截断做用域链,避免闭包形成引用变量没法释放。利用当即执行特性,返回须要的业务函数或对象,避免每次经过条件判断来处理
场景:通常用于框架、插件等场景
14.html和xhtml有什么区别?
HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的标记语言。
1.XHTML 元素必须被正确地嵌套。
2.XHTML 元素必须被关闭。
3.标签名必须用小写字母。
4.空标签也必须被关闭。
5.XHTML 文档必须拥有根元素。
15. 什么是构造函数?与普通函数有什么区别?
构造函数:是一种特殊的方法、主要用来建立对象时初始化对象,总与new运算符一块儿使用,建立对象的语句中构造函数的函数名必须与类名彻底相同。
与普通函数相比只能由new关键字调用,构造函数是类的标示
16. 经过new建立一个对象的时候,函数内部有哪些改变
function Person(){} Person.prototype.friend = []; Person.prototype.name = ''; // var a = new Person(); // a.friend[0] = '王琦'; // a.name = '程娇'; // var b = new Person(); // b.friend? // b.name?
一、建立一个空对象,而且 this 变量引用该对象,同时还继承了该函数的原型。
二、属性和方法被加入到 this 引用的对象中。
三、新建立的对象由 this 所引用,而且最后隐式的返回 this 。
17.事件委托?有什么好处?
(1)利用冒泡的原理,把事件加到父级上,触发执行效果
(2)好处:新添加的元素还会有以前的事件;提升性能。
18.window.onload ==? DOMContentLoaded ?
通常状况下,DOMContentLoaded事件要在window.onload以前执行,当DOM树构建完成的时候就会执行DOMContentLoaded事件,而window.onload是在页面载入完成的时候,才执行,这其中包括图片等元素。大多数时候咱们只是想在DOM树构建完成后,绑定事件到元素,咱们并不须要图片元素,加上有时候加载外域图片的速度很是缓慢。
19.节点类型?判断当前节点类型?
1. 元素节点
2. 属性节点
3. 文本节点
8. 注释节点
9. 文档节点
经过nodeObject.nodeType判断节点类型:其中,nodeObject 为DOM节点(节点对象)。该属性返回以数字表示的节点类型,例如,元素节点返回 1,属性节点返回 2 。
20.如何合并两个数组?数组删除一个元素?
//三种方法。 (1)var arr1=[1,2,3]; var arr2=[4,5,6]; arr1 = arr1.concat(arr2); console.log(arr1); (2)var arr1=[1,2,3]; var arr2=[4,5,6]; Array.prototype.push.apply(arr1,arr2); console.log(arr1); (3)var arr1=[1,2,3]; var arr2=[4,5,6]; for (var i=0; i < arr2.length; i++) { arr1.push( arr2[i] ); } console.log(arr1);
21.强制转换 显式转换 隐式转换?
//强制类型转换: Boolean(0) // => false - 零 Boolean(new object()) // => true - 对象 Number(undefined) // => NaN Number(null) // => 0 String(null) // => "null" parseInt( ) parseFloat( ) JSON.parse( ) JSON.stringify ( )
隐式类型转换:
在使用算术运算符时,运算符两边的数据类型能够是任意的,好比,一个字符串能够和数字相加。之因此不一样的数据类型之间能够作运算,是由于JavaScript引擎在运算以前会悄悄的把他们进行了隐式类型转换的
(例如:x+"" //等价于String(x)
+x //等价于Number(x)
x-0 //同上
!!x //等价于Boolean(x),是双叹号)显式转换:
若是程序要求必定要将某一类型的数据转换为另外一种类型,则能够利用强制类型转换运算符进行转换,这种强制转换过程称为显示转换。
显示转换是你定义让这个值类型转换成你要用的值类型,是底到高的转换。例 int 到float就能够直接转,int i=5,想把他转换成char类型,就用显式转换(char)i
22. Jq中如何实现多库并存?
Noconfict 多库共存就是“$ ”符号的冲突。
方法一: 利用jQuery的实用函数.noConflict();这个函数归还.noConflict();这个函数归还的名称控制权给另外一个库,所以能够在页面上使用其余库。这时,咱们能够用"jQuery "这个名称调用jQuery的功能。 .noConflict();
jQuery('#id').hide();
.....
//或者给jQuery一个别名
var.noConflict(); jQuery('#id').hide(); ..... //或者给jQuery一个别名 varj=jQuery
$j('#id').hide();
.....方法二: (function($){})(jQuery)
方法三: jQuery(function())通过传递一个函数做为jQuery的参数,因此把这个函数声明为就绪函数。我们声明))经过传递一个函数做为jQuery的参数,所以把这个函数声明为就绪函数。咱们声明为就绪函数的参数,由于jQuery老是吧jQuery对象的引用做为第一个参数传递,因此就保证了函数的执行。
23.Jq中get和eq有什么区别?
get() :取得其中一个匹配的元素。num表示取得第几个匹配的元素,get多针对集合元素,返回的是DOM对象组成的数组 eq():获取第N个元素,下标都是从0开始,返回的是一个JQuery对象
24.如何经过原生js 判断一个元素当前是显示仍是隐藏状态?
if( document.getElementById("div").css("display")==='none') if( document.getElementById("div").css("display")==='block') $("#div").is(":hidden"); // 判断是否隐藏 $("#div").is(":visible")
25.Jq如何判断元素显示隐藏?
//第一种:使用CSS属性 var display =$('#id').css('display'); if(display == 'none'){ alert("我是隐藏的!"); } //第二种:使用jquery内置选择器 <div id="test"> <p>仅仅是测试所用</p> </div> if($("#test").is(":hidden")){ $("#test").show(); //若是元素为隐藏,则将它显现 }else{ $("#test").hide(); //若是元素为显现,则将其隐藏 } //第三种:jQuery判断元素是否显示 是否隐藏 var node=$('#id'); if(node.is(':hidden')){ //若是node是隐藏的则显示node元素,不然隐藏 node.show(); }else{ node.hide(); }
26.移动端上什么是点击穿透?
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件跨页面点击穿透问题:若是按钮下面刚好是一个有href属性的a标签,那么页面就会发生跳转另外一种跨页面点击穿透问题:此次没有mask了,直接点击页内按钮跳转至新页,而后发现新页面中对应位置元素的click事件被触发了解决方案:
一、只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内全部click所有换成touch事件( touchstart 、’touchend’、’tap’)二、只用click
下下策,由于会带来300ms延迟,页面内任何一个自定义交互都将增长300毫秒延迟三、tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms仍是能感受到慢的四、pointer-events
比较麻烦且有缺陷, 不建议使用mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应缺陷是mask消失后的的350ms内,用户能够看到按钮下面的元素点着没反应,若是用户手速很快的话必定会发现
27.Jq绑定事件的几种方式?on bind ?
jQuery中提供了四种事件监听方式,分别是bind、live、delegate、on,对应的解除监听的函数分别是unbind、die、undelegate、off
Bind( )是使用频率较高的一种,做用就是在选择到的元素上绑定特定事件类型的监听函数;
Live( )能够对后生成的元素也能够绑定相应的事件,处理机制就是把事件绑定在DOM树的根节点上,而不是直接绑定在某个元素上;
Delegate( )采用了事件委托的概念,不是直接为子元素绑定事件,而是为其父元素(或祖先元素也可)绑定事件,当在div内任意元素上点击时,事件会一层层从event target向上冒泡,直至到达你为其绑定事件的元素;
on( )方法能够绑定动态添加到页面元素的事件,on()方法绑定事件能够提高效率;
28.Jq中如何将一个jq对象转化为dom对象?
方法一:
jQuery对象是一个数据对象,能够经过[index]的方法,来获得相应的DOM对象。
如:var v=v=("#v") ; //jQuery对象
var v=$v[0]; //DOM对象
alert(v.checked) //检测这个checkbox是否被选中方法二:
jQuery自己提供,经过.get(index)方法,获得相应的DOM对象
如:var v=v=("#v"); //jQuery对象
var v=$v.get(0); //DOM对象
alert(v.checked) //检测这个checkbox是否被选中
29.Jq中有几种选择器?分别是什么?
层叠选择器、基本过滤选择器、内容过滤选择器、可视化过滤选择器、属性过滤选择器、子元素过滤选择器、表单元素选择器、表单元素过滤选择器
30.Jq中怎么样编写插件?
//第一种是类级别的插件开发: //1.1 添加一个新的全局函数 添加一个全局函数,咱们只需以下定义: jQuery.foo = function() { alert('This is a test. This is only a test.'); }; //1.2 增长多个全局函数 添加多个全局函数,可采用以下定义: jQuery.foo = function() { alert('This is a test. This is only a test.'); }; jQuery.bar = function(param) { alert('This function takes a parameter, which is "' + param + '".'); }; 调用时和一个函数的同样的:jQuery.foo();jQuery.bar();或者$.foo();$.bar('bar'); //1.3 使用jQuery.extend(object); jQuery.extend({ foo: function() { alert('This is a test. This is only a test.'); }, bar: function(param) { alert('This function takes a parameter, which is "' + param +'".'); } }); //1.4 使用命名空间 // 虽然在jQuery命名空间中,咱们禁止使用了大量的javaScript函数名和变量名。 // 可是仍然不可避免某些函数或变量名将于其余jQuery插件冲突,所以咱们习惯将一些方法 // 封装到另外一个自定义的命名空间。 jQuery.myPlugin = { foo:function() { alert('This is a test. This is only a test.'); }, bar:function(param) { alert('This function takes a parameter, which is "' + param + '".'); } }; //采用命名空间的函数仍然是全局函数,调用时采用的方法: $.myPlugin.foo(); $.myPlugin.bar('baz'); //经过这个技巧(使用独立的插件名),咱们能够避免命名空间内函数的冲突。 //第二种是对象级别的插件开发 //形式1: (function($){ $.fn.extend({ pluginName:function(opt,callback){ // Our plugin implementation code goes here. } }) })(jQuery); //形式2: (function($) { $.fn.pluginName = function() { // Our plugin implementation code goes here. }; })(jQuery); //形参是$,函数定义完成以后,把jQuery这个实参传递进去.当即调用执行。 //这样的好处是,咱们在写jQuery插件时,也可使用$这个别名,而不会与prototype引发冲突
31.(′div+.ab′)和(′div+.ab′)和('.ab+div') 哪一个效率高?
$('div+.ab')效率高
32..map和.map和.each有什么区别
map()方法主要用来遍历操做数组和对象,会返回一个新的数组。$.map()方法适用于将数组或对象每一个项目新阵列映射到一个新数组的函数;
each()主要用于遍历jquery对象,返回的是原来的数组,并不会新建立一个数组。
33.编写一个 getElementsByClassName 封装函数?
<body> <input type="submit" id = "sub" class="ss confirm btn" value="提交"/> <script> window.onload = function(){ //方法一 var Opt = document.getElementById('sub'); var getClass = function(className,tagName){ if(document.getElementsByTagName){ var Inp = document.getElementsByTagName(tagName); for(var i=0; i<Inp.length; i++){ if((new RegExp('(\\s|^)' +className +'(\\s|$)')).test(Inp[i].className)){ return Inp[i]; } } }else if(document.getElementsByClassName){ return document.getElementsByClassName(className); } } //方法二 var aa = getClass("confirm", "input"); function getClass(className, targetName){ var ele = []; var all = document.getElementsByTagName(targetName || "*"); for(var i=0; i<all.length; i++){ if(all[i].className.match(new RegExp('(\\s|^)'+confirm+'(\\s|$)'))){ ele[ele.length] = all[i]; } } return ele; } //方法三 function getObjsByClass(tagName, className){ if(document.getElementsByClassName){ alert("document.getElementsByClassName"); return document.getElementsByClassName(className); }else{ var el = []; var _el = document.getElementsByTagName(tagName);