JavaScript面试2

1.你觉得js是一门怎样的语言,它与你学过的其他语言有什么不同

javaScript

​ 一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML网页上使用,用来给HTML网页增加动态功能。JavaScript兼容于ECMA标准,因此也称为ECMAScript。

Javascript的特点:

一、简单性:

JavaScript是一种基于Java基本语句和控制流之上的简单而紧凑的设计,从而对于学习Java是一种非常好的过渡。它的变量类型是采用弱类型,并未使用严格的数据类型。

二、动态性:

avaScript是动态的,它可以直接对用户或客户输入做出响应,无须经过Web服务程序。它对用户的反映响应,是采用以事件驱动的方式进行的。所谓事件驱动,就是指在主页(Home Page)中执行了某种操作所产生的动作,就称为“事件”(Event)。比如按下鼠标、移动窗口、选择菜单等都可以视为事件。当事件发生后,可能会引起相应的事件响应。

三、跨平台性:

JavaScript是依赖于浏览器本身,与操作环境无关,只要能运行浏览器的计算机,并支持JavaScript的浏览器就可正确执行。从而实现了“编写一次,走遍天下”的梦想。

四、安全性:

JavaScript是一种安全性语言,它不允许访问本地的硬盘,并不能将数据存入到服务器上,不允许对网络文档进行修改和删除,只能通过浏览器实现信息浏览或动态交互。从而有效地防止数据的丢失。

2。从静态类型还是动态类型来看

静态类型,编译的时候就能够知道每个变量的类型,编程的时候也需要给定类型,如Java中的整型int,浮点型float等。C、C++、Java都属于静态类型语言。

动态类型,运行的时候才知道每个变量的类型,编程的时候无需显示指定类型,如JavaScript中的var、PHP中的$。JavaScript、Ruby、Python都属于动态类型语言。

静态类型还是动态类型对语言的性能有很大影响。

对于静态类型,在编译后会大量利用已知类型的优势,如int类型,占用4个字节,编译后的代码就可以用内存地址加偏移量的方法存取变量,而地址加偏移量的算法汇编很容易实现。

对于动态类型,会当做字符串通通存下来,之后存取就用字符串匹配。

从编译型还是解释型来看

编译型语言,像C、C++,需要编译器编译成本地可执行程序后才能运行,由开发人员在编写完成后手动实施。用户只使用这些编译好的本地代码,这些本地代码由系统加载器执行,由操作系统的CPU直接执行,无需其他额外的虚拟机等。

源代码=》抽象语法树=》中间表示=》本地代码

解释性语言,像JavaScript、Python,开发语言写好后直接将代码交给用户,用户使用脚本解释器将脚本文件解释执行。对于脚本语言,没有开发人员的编译过程,当然,也不绝对。

源代码=》抽象语法树=》解释器解释执行。

对于JavaScript,随着Java虚拟机JIT技术的引入,工作方式也发生了改变。可以将抽象语法树转成中间表示(字节码),再转成本地代码,如JavaScriptCore,这样可以大大提高执行效率。也可以从抽象语法树直接转成本地代码,如V8

​ Java语言,分为两个阶段。首先像C++语言一样,经过编译器编译。和C++的不同,C++编译生成本地代码,Java编译后,生成字节码,字节码与平台无关。第二阶段,由Java的运行环境也就是Java虚拟机运行字节码,使用解释器执行这些代码。一般情况下,Java虚拟机都引入了JIT技术,将字节码转换成本地代码来提高执行效率。

注意,在上述情况中,编译器的编译过程没有时间要求,所以编译器可以做大量的代码优化措施。

对于JavaScript与Java它们还有的不同:

对于Java,Java语言将源代码编译成字节码,这个同执行阶段是分开的。也就是从源代码到抽象语法树到字节码这段时间的长短是无所谓的。

对于JavaScript,这些都是在网页和JavaScript文件下载后同执行阶段一起在网页的加载和渲染过程中实施的,所以对于它们的处理时间有严格要求

2.js基本数据类型

字符串值,数值,布尔值,数组,undefined,null,对象。
基本类型数据
1.基本数据类型值是指简单的数据段,五种基本类型都是按值访问的(可以操作保存在变量中的实际值);
2.基本类型的值在内存中占据固定大小的空间,被保存在栈内存中。(从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本);
3.不能给基本类型的值添加属性。
引用类型数据:object(还有array、function)
1.引用类型值是指那些可以由多个值构成的对象。js不允许直接访问内存中的位置,也就是不能直接访问操作对象的内存空间,在操作对象时,实际上是在操作对象的引用而不是实际的对象;
2.引用类型的值是对象,保存在堆内存中,包含引用类型值的变量实际上包含的并不是对象本身,而是指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终指向同一个对象。
3.对于引用类型的值,可以为其添加属性和方法,也可以改变和删除其属性和方法。
4.在ECMAScript中用var关键字来定义变量,因为js是弱类型的,所以无法确定变量一定会存储什么值,也就不知道变量到底会是什么类型,而且变量的类型可以随时改变。这就是ECMAScript是松散类型的来由,所谓松散类型就是可以用来保存任何类型的数据。
在es6中新增了let命令来声明变量,const命令声明一个只读的常量
let的用法类似于var,但是所声明的变量,只有在let代码块内才有效;const一旦声明,常量的值就不能改变。

https://www.cnblogs.com/zhengyeye/p/6485124.html

3.js如何判断变量数据类型

typeof(typeof的局限性在于 数组、对象、null都为object;typeof运算符把函数返回function)、instanceof([1,2] instanceof Array 只对数组有用)、Array.isArray()方法确定某个值是否为数组、Object.prototype.toString.call()(最理想,能够十分准确检测出全部类型)、constructor(引用了初始化该对象的构造函数来判断 ((“123”).constructor === String)

4.类数组和数组

类数组定义
1)拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理);
2)不具有数组所具有的方法;
javascript中常见的类数组有 arguments对象和 DOM方法的返回结果。比如 document.getElementsByTagName()

判断是否是类数组

1
2
3
4
5
function isLikeArray(o) {
if(typeof o === 'object'&& isFinite(o.length) && o.length >= 0 && o.length < 4294967296){// 4294967296: 2^32
return true} else{
return false}
}

5.将类数组转换为数组

  1. 创建一个新的数组,然后将将类数组中的元素添加到新数组里面
  2. Array.prototype.slice.call()
  3. Array.form(arguments)

6.如何遍历数组

1.普通for循环

1
2
3
4
5
6
for(var i = 0; i < arr.length; i++){
}
for(var i = 0,len = arr.length; i < len; i++){
}
for(var i = 0; arr[i] != null; i++){
}

2.for in 循环

1
2
for(i in arr){
}

3.forEach循环

1
2
3
arr.forEach(function(e){
});
//数组自带的foreach循环,使用频率较高,实际上性能比普通for循环弱

4.map遍历

1
2
arr.map(function(n)){
});

5.for of 遍历

1
2
3
for (let value of arr){
});
//这种方式是es6里面用到的,性能好于for in,但仍比不上普通for循环

https://blog.csdn.net/function__/article/details/79555301

7.ARRAY常用方法

push(),pop(),shift(),unshift(),splice(),sort(),reverse(),map(),forEach(),isArray(),toString()等

8.STRING常用方法

toUpperCase():把一个字符串全部变为大写

toLowerCase():把一个字符串全部变为小写

indexOf():会搜索制定字符串出现的位置,有返回索引,没有返回-1

substring():返回制定索引区间的子串(传一个参数的话表示从该参数索引位置开始到结束;传两个参数的话表示从开始索引到结束索引)

slice():使用与substring()基本相同,可以传负数,负数则从字符串尾部算起;substring()不能传负数

substr():用法与上面两个相似,但是第二个参数表示截取的字符串最大长度(三种字符串截取方法,未填第二参数时,自动截取起始位置到字符串末尾)

toString():可以将其他数据类型转换为字符串

split():对字符串进行分割,返回一个数组(如果只传一个参数则表示以哪个字符进行分割;传两个参数的话第二个参数表示返回的字符串数组的最大长度)

replace():字符串替换,默认只进行第一次匹配操作的替换,想要全局替换,需要加上正则全局标识g。例:

1
2
3
4
    var mystr="wozaijinxingzifuchuantihuancaozuo,zifuchuantihuano";
    var replaceStr=mystr.replace("zifuchuan"," "); //wozaijinxing tihuancaozuo,zifuchuantihuano
    var replaceStr=mystr.replace(/zifuchuan/," "); //wozaijinxing tihuancaozuo,zifuchuantihuano
    var replaceStr=mystr.replace(/zifuchuan/g," "); //wozaijinxing tihuancaozuo, tihuano

length:获取字符串长度

indexOf():查询子字符串,对大小写敏感,返回字符串中子串第一处出现的索引(从左到右)。如果没有匹配项,返回-1。

lastIndexOf():查询子字符串,对大小写敏感,返回字符串中子串第一处出现的索引(从右到左)。如果没有匹配项,返回-1。

charAt():返回制定位置的字符

match():字符串匹配。若有相匹配的字符,则返回所要匹配的字符串;没有相匹配的,返回null(也可定义一个变量为正则表达式进行匹配)

exec():字符串匹配。与match()效果相同,用法相反

search():进行正则匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回-1

trim():删除字符串前后的空格

9.DOM 事件级别

dom0级事件就是在js中写到 element.onclick=function(){},是一种比较传统的方式:把一个函数(或者匿名函数)赋值给一个事件的处理程序属性。

优势(兼容所有浏览器)

缺点:不能给元素添加多个事件处理程序,只能添加一个,如果添加多个事件处理程序,后面的会覆盖前面的

2 DOM1级主要是映射文档,没有事件

3 DOM2级事件 element.addEventListerner(‘click’,function(){},false) false指的是冒泡,早期浏览器都支持冒泡,为了兼容基本上最后一个参数都是false.

删除事件:element.removeEventListener(‘click’,function(){},false),这样的删除方式只能删除DOM2级添加的事件。删除的时候传递的参数必须跟添加时传递的参数一样才能正确删除事件。

优点,可以给元素添加多个事件处理程序,这些事件处理程序按照他们的顺序执行。

4 Dom3级事件跟dom2级事件写法一样的,只是增加了许多事件类型,包括点击事件和键盘事件。

10.DOM 事件类型

Web浏览器中可能发生的事件有很多类型。不同的事件类型具有不同的信息,而“DOM3级事件”规定了以下几类事件:

  • UI(用户界面)事件,当用户与界面上的元素交互时触发
  • 焦点事件,当元素获得或失去焦点时触发
  • 鼠标事件,当用户通过鼠标在页面上执行操作时触发
  • 滚轮事件,当使用鼠标滚轮时触发
  • 文本事件,当在文档中输入文本时触发
  • 键盘事件,当用户通过键盘在页面上执行操作时触发
  • 合成事件,当为IME输入字符时触发
  • 变动事件,当底层DOM结构发生变化时触发

11.DOM 事件流

什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段。
事件捕获阶段
处于目标阶段
事件冒泡阶段

首先发生的是事件捕获,为截获事件提供了机会;然后是实际的目标接收到事件;最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。

addEventListener:addEventListener 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。
IE只支持事件冒泡。

img12.描述一下冒泡/事件捕获的具体流程

1.事件冒泡:即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。

2.事件捕获:思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

13.html、dom0、dom2是如何注册事件

1.在html代码元素中添加事件为Html事件。

1
<input type="button" value="按钮" id="btn1" onclick="showMess()"/>

2.使用元素的onclick方法为DOM0级事件处理。

1
btn2.onclick=null;

3.使用事件添加方法为元素添加事件(

1
2
chrome:addEventListener,removeEventListener
IE:attachEvent,detachEvent

)为DOM2级事件处理。

14.事件流

JavaScript高级程序设计–p345

15.事件委托(代理)

https://www.jianshu.com/p/a77d8928c5c9

16.自定义事件

 1.Event() 构造函数, 创建一个新的事件对象 Event
 2.CustomEvent() 创建一个自定义事件
 3.document.createEvent() 创建一个新的事件(Event),随之必须调用自身的 init 方法进行初始化
4.https://www.cnblogs.com/shapeY/p/7923353.html

17.怎么防止冒泡

1
2
3
4
5
6
7
8
9
function stopBubble(e) { 
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}

阻止默认行为

http://caibaojian.com/javascript-stoppropagation-preventdefault.html

1
2
3
4
5
6
7
8
9
10
//阻止浏览器的默认行为 
function stopDefault( e ) {
//阻止默认浏览器动作(W3C)
if ( e && e.preventDefault )
e.preventDefault();
//IE中阻止函数器默认动作的方式
else
window.event.returnValue = false;
return false;
}

18.谈谈innerHTML、 nodeValue与 textContent之间的区别

nodeValue:是节点的值

innerHTML:浏览器会将内容解析为HTML代码

textContent:使用纯文本而不是解析为HTML

19.简单说一下DOM操作中如何查找元素

document.getElementById(id) 通过元素 id 来查找元素

document.getElementsByTagName(name) 通过标签名来查

document.getElementsByClassName(name) 通过类名来查

document.getElementsByName();//name属性值,一般不用

* 通过css选择器查找HTML元素 (document.querySelector()返回与该模式匹配的第一个元素,结果为一个元素;如果没找到匹配的元素,则返回null)

* 通过HTML对象选择器查找HTML对象

20.dom节点获取,及其特性

通过 JavaScript,您可以使用以下节点属性在节点之间导航:

parentNode

childNodes[nodenumber]

firstChild

lastChild

nextSibling

previousSibling

21.如果一个 ul 下面有 5个 li 如何给他们添加点击事情的方法

js为li列表添加点击事件 - caoPengFlying的博客 - CSDN博客

JS中for循环出现的问题:如何给li元素绑定事件,点击每个li元素弹出对应的 - 骆小胖~ - CSDN博客

22.window document 对象是什么?

window对象

代表浏览器中的一个打开的窗口或者框架,window对象会在或者每次出现时被自动创建,在客户端JavaScript中,Window对象是全局对象,所有的表达式都在当前的环境中计算,要引用当前的窗口不需要特殊的语法,可以把那个窗口属性作为全局变量使用,例如:可以只写document,而不必写window.document。同样可以把窗口的对象方法当做函数来使用,如:只写alert(),而不必写window.alert

window对象实现了核心JavaScript所定义的全局属性和方法。

indow对象的window属性和self属性引用都是他自己。

document对象

代表整个HTML文档,可以用来访问页面中的所有元素 。

每一个载入浏览器的HTML文档都会成为document对象。document对象使我们可以从脚本中对HTML页面中的所有元素进行访问。
document对象是window对象的一部分可以通过window.document属性对其进行访问
HTMLDocument接口进行了扩展,定义HTML专用的属性和方法,很多属性和方法都是HTMLCollection对象,其中保存了对锚、表单、链接以及其他可脚本元素的引用。

23.setTimeout 和 setInteval 的区别和使用方法

https://blog.csdn.net/HandSome_He/article/details/81676640

24.异步同步

异步

如果在函数返回的时候,调用者还不能购得到预期结果,而是将来通过一定的手段得到(例如回调函数),这就是异步。例如ajax操作。
如果函数是异步的,发出调用之后,马上返回,但是不会马上返回预期结果。调用者不必主动等待,当被调用者得到结果之后会通过回调函数主动通知调用者。

同步

如果在函数返回结果的时候,调用者能够拿到预期的结果(就是函数计算的结果),那么这个函数就是同步的.如果函数是同步的,即使调用函数执行任务比较耗时,也会一致等待直到得到执行结果。

25.如何实现页面跳转

第一种:直接跳转加参数

1
2
    <script language="javascript" type="text/javascript">           window.location.href="login.jsp?backurl="+window.location.href;
</script>

直接跳转无参数:

1
<script>window.location.href='http://www.baidu.com';</script>

第二种:返回上一次预览界面

1
<script language="javascript">alert("返回");window.history.back(-1);</script>标签嵌套:
1
<a href="javascript:history.go(-1)">返回上一步<a><a href="<%=Request.ServerVariables("HTTP_REFERER")%>">返回上一步</a>

第三种:指定跳转页面 对框架无效。。。

1
<script language="javascript">       window.navigate("top.jsp");  </script>

第四种:指定自身跳转页面 对框架无效。。

1
<script language="JavaScript">          self.location='top.htm';   </script>

第五种:指定自身跳转页面 对框架有效。。

1
<script language="javascript">          alert("非法访问!");          top.location='xx.aspx';   </script>

第六种:按钮式 在button按钮添加 事件跳转。。

1
<input name="pclog" type="button" value="GO" onClick="location.href='login.aspx'">

第七种:在新窗口打开:

1
 <a href="javascript:" onClick="window.open('login.aspx','','height=500,width=611,scrollbars=yes,status=yes')">开新窗口</a>

26.children 和 childNodes 的区别

childNodes:获取节点,不同浏览器表现不同;

  IE:只获取元素节点;

  非IE:获取元素节点与文本节点;

  解决方案:if(childNode.nodeName==”#text”) continue 或者 if(childNode.nodeType != ‘3’) continue

2、children:获取元素节点,浏览器表现相同。

  因此建议使用children。

27.如何实现insertAfter

parent.insertBefore(newElement,targetElement.nextSibling)他的三部分为 父节点 新节点 目标节点 他会把新节点创建在目标节点之前 需要注意的是 父节点并无需获取 你通过目标节点.parentNode就可以获取
但是js并没有提供插入在目标节点之后的方法 我们可以自己写一个

1
2
3
4
5
6
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement){
parent.appendChild(newElement);
} else { parent.insertBefore(newElement,targetElement.nextSibling);
}

首先 他把目标节点的父节点找到包装在parent里 然后进行对比 如果这个父节点的最后一个节点是目标节点 那么无需插入在中间 因为appendChild默认就是将节点插入到末尾

如果不是 目标节点游在中间 那么他会调用Before方法 把新节点插入到 目标节点的后面一个节点之前 其实也就是他的节点之后 绕了一点

28.变量提升

JavaScript 变量提升 - 云+社区 - 腾讯云

29.执行环境与作用域

https://www.jb51.net/article/83585.htm

30.克隆对象

31.this以及修改this

https://www.cnblogs.com/yummylucky/p/10225066.html

32.call和apply区别

通过apply和call改变函数的this指向,他们两个函数的第一个参数都是一样的表示要改变指向的那个对象,第二个参数,apply是数组,而call则是arg1,arg2…这种形式(两者区别仅在于接收参数的方式不同。apply()方法第二个参数可以是Array的实例也可以是argument对象,call()方法必须明确地传入每一个参数)。通过bind改变this作用域会返回一个新的函数,这个函数不会马上执行。

apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。

call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

bind除了返回是函数以外,它的参数和call一样。

33.闭包

一句话可以概括:闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。

(1)什么是闭包: 闭包是指有权访问另外一个函数作用域中的变量的函数。闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。

(2)为什么要用: 匿名自执行函数:我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。 结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

34.js运行机制

https://www.baidu.com/link?url=HbzsQy4I1L5Y8RWr5NEReBaQkfm4vCCrb7qa9KYGo0tAglavxUxtAFUCZ2uxKxsEFl3ToD2XukSuaPtSDSDgcWGQmN2PlrmRRrj-ZRpq7g7&wd=&eqid=bfa5949d0000d54b000000065d294ed0

35.js对象的创建方法

js中对象与对象创建方法的各种方法_javascript技巧_脚本之家

36.原型链

JS重点整理之JS原型链彻底搞清楚 - sinat_21274091的博客 - CSDN博客

37.对象的继承机制

详解JavaScript对象继承方式 - 雨霖月寒 - 博客园

38.JS垃圾回收机制

面试题——js垃圾回收机制和引起内存泄漏的操作 - yingzizizizizizzz的专栏 - CSDN博客