JavaScript、ES6基础面试题及答案解析②
-
- 1、js基本数据类型有哪些?
- 2、Ajax如何使用
- 3、如何判断一个数据类型是NaN?
- 4、闭包是什么?有什么特性?对页面有什么影响?
- 5、谈谈js中常见的内存泄漏:
- 6、事件委托是什么?如何确定事件源(Event.target 谁调用谁就是事件源)
- 7、什么是事件冒泡?怎么阻止事件冒泡?
- 8、本地存储与cookie的区别
- 9、ES6新特性
- 10、谈谈对let、var与const的区别的理解
- 11、数组方法有哪些?请简述:
- 12、说出两种以上数组去重的方法
- 13、什么是面试对象(OOP)请简述
- 14、说说普通函数和构造函数的区别
- 15、请简述原型、原型链、(原型)继承
- 16、Promise的理解
- 17、请简述async的用法
- 18、一个页面从输入url到页面加载显示完成,这个过程都发生了什么?
- 19、请简述js中 .call()与 .apply() 的区别。
- 20、为什么会造成跨域?请简述同源策略。
- 21、请说说This的指向问题
- 22、什么是jsonp 工作原理是什么?他为什么不是真正的ajax?
- 23、请说出简单的类与继承
- 24、简述同步与异步的区别,阻塞与非阻塞的区别
- 25、为什么js是弱类型语言?
- 26、箭头函数与普通函数的区别
- 27、For循环与map循环的区别?
- 28、原型和继承,prototype,call和apply继承的区别(第一个参数是相同的,第二个的区别在哪)
- 29、深浅拷贝是什么?如何实现?
- 30、什么时候用深拷贝/浅拷贝?
- 31、什么是js内存泄露?
- 32、什么是csrf攻击?
- 33、预加载和懒加载的区别,预加载在什么时候加载合适?
- 34、谈谈Js的函数节流和函数防抖的区别
1、js基本数据类型有哪些?
答:字符串String,数值Number,布尔 boolean,null,undefined,对象,数组
2、Ajax如何使用
一个完整的AJAX请求包括五个步骤:
-
创建XMLHTTPRequest对象
-
使用open方法创建http请求,并设置请求地址:
xhr.open(get/post , url , async , true(异步) )经常使用前三个参数
-
设置发送的数据,用send发送请求
-
注册事件(给ajax设置事件)
-
获取相应并更新页面
3、如何判断一个数据类型是NaN?
NaN 非数字 但是用typeof 检测是 Number 类型
- 利用NaN的定义,用typeof判断是否为Number类型并且判断是否满足isnan
- 利用NaN是唯一一个不等于任何自身的特点 n! == n
- 利用ES6中提供的Object.is()方法(判断两个值是否相等)n==nan
js中null与undefined的区别:
相同点:用if判断时,;两者都会被转为false
不同点:
- number转换的值不同 number(null)为0 number(undefined)为NaN
- null表示一个被值被定义了,但是这个值是空值
- undefined 变量声明但未赋值
4、闭包是什么?有什么特性?对页面有什么影响?
闭包可以简单理解成:定义在一个函数内部的函数。其中一个内部函数在包含他们的外部函数之外被调用时,就会形成闭包。
特点:
- 函数嵌套函数。
- 函数内部可以引用外部的参数和变量。
- 参数和变量不会被垃圾回收机制回收。
使用:
- 读取函数内部的变量;
- 这些变量的值始终保存在内存中,不会再外层函数调用后被自动清除。
优点:
- 变量长期驻扎在内存中;
- 避免全局变量的污染;
- 私有成员的存在;
**缺点:**会造成内存泄漏
5、谈谈js中常见的内存泄漏:
- 意外的全局变量
- 被遗忘的计时器或回调函数
- 脱离DOM的引用
- 闭包
6、事件委托是什么?如何确定事件源(Event.target 谁调用谁就是事件源)
js高程上将:事件委托就是利用事件冒泡,只制定一个时间处理程序,就可以管理某一类型的所有事件。
事件委托,称事件代理,是js中很常见的绑定事件的技巧,事件委托就是把原本需要绑定在子元素的所有响应事件委托给父元素,让父元素担当事件监听的职务,事件委托的原理是DOM元素的事件冒泡。
7、什么是事件冒泡?怎么阻止事件冒泡?
一个事件触发后,会在子元素和父元素之间传播,这种传播分为三个阶段:
- 捕获阶段:从window对象传导到目标节点(从里到外)
- 目标阶段:在目标节点上触发
- 冒泡阶段:从目标节点传回到window对象(从里到外)
事件委托/事件代理就是利用事件冒泡的机制把里层需要响应的事件绑定到外层
阻止事件冒泡
- 标准写法:e.stopPropagation()
- IE6-8的非标准写法:e.cancelBubble = true
8、本地存储与cookie的区别
cookie是小饼干的意思。说以cookie确实非常小,他的大小限制为4kb左右。他的主要用途有保存用户登录信息。
localStorage
localStorage是HTML5标准中新加入的技术,他并不是什么划时代的新东西。早在IE6时代,就有一个叫userData的东西用于本地存储,而当时考虑到浏览器的兼容性,更通用的方案是Flsah。而如今,localStorage北大多数浏览器所支持,如果你的网站需要兼容IE6+,那么使用userData方案是不错的选择
sessionStorage
sessionStorage与localStorage的接口类似,但保存数据的生命周期与localStorage不同。session这个词的翻译的意思就是“会话”。而sessionStorage是一个前端的概念,他只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存在。但当页面关闭后,
sessionStorage中的数据就会被清空。
散着的异同
9、ES6新特性
const和let、模板字符串、箭头函数、函数的参数默认值、对象和数组解构、for…of 和 for…in、ES6中的类
10、谈谈对let、var与const的区别的理解
- var声明的变量会挂载在window上,而let 和const 声明的变量不会
- var 声明的变量存在变量提升,let和const不存在变量提升
- 同一作用域下var 可以声明同名变量,let 和const 不可以
- let 和const 声明会形成块级作用域
- let 暂存死区
- const 一旦声明必须赋值,不能用null占位,声明后不能在修改,如果声明的是复合数据类型,可以修改属性
11、数组方法有哪些?请简述:
- push() 从后面添加元素,返回值为添加完后新数组的长度
- arr.pop() 从后面删除元素,只能是一个,返回值是删除的元素
- arr.shift() 从前面删除元素,只能删除一个 返回值是删除的元素
- arr.unshift() 从前面添加元素,返回值添加完后的数组的长度
- arr.splice(i,n) 删除从i(索引值)开始之后的那个元素。返回值是删除的元素
- arr.concat() 连接两个数组 返回值为连接后的新数组
- str.split() 将字符串转化为数组
- arr.sort() 将数组进行排序,返回值是排好的数组,默认是按照最左边的数字进行排序,不是按照数字大小进行排序的
- arr.reverse() 将数组反转,返回值是反转后的数组
- arr.slice(start,end) 切去索引值start到索引值end的数组,不包含end索引值的值,返回值是切出来的数组
- arr.forEach(callback) 遍历数组,无return 即使有return,也不会返回任何值,并且会影响原来的数组
- arr.map(callback) 映射数组(遍历数组),有return 返回一个新的数组
- arr.filter(callback) 过滤数组,返回一个满足要求的数组
12、说出两种以上数组去重的方法
- 使用indexof()方法
- 使用lastindexof() 方法和indexof() 方法一样 indexof从头部开始匹配 lastindexof从尾部匹配
- ES6的set结构 set不接受重复数据
- 使用sort方法先将数组升序排序,然后与相邻的比较,如果不同则存入新数组
- 使用filter和indexof方法
- 使用ES6的set和扩展运算符
- 使用set和Array.from() 方法 array.from可以将set结构转成数组
- 使用splice 和双重循环
- 使用includes方法
13、什么是面试对象(OOP)请简述
面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节;这种思想是将数据作为第一位,这是对数据的一种优化,操作起来更加的方便,简化了过程。
js本身是没有class类型的,但是每个函数都有一个prototype属性,prototype指向一个对象,当函数作为构造函数时,prototype就起到类似class的作用
面向对象有三个特点
- 封装(隐藏对象的属性和实现细节,对外提供公共访问方式)
- 继承(提高代码复用性,继承是多态的前提)
- 多态(是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象)
14、说说普通函数和构造函数的区别
- 构造函数也是一个函数,创建方式和普通函数一样,但是构造函数习惯上首字母大写
- 调用方式不一样,普通函数直接调用,构造函数要用关键字new来调用
- 调用时,构造函数内部会创建一个新对象,就是实例,普通函数不回创建新的对象
- 构造函数内部的this指向实例,普通函数内部的this指向调用函数的对象(如果没有调用,默认为window)
- 构造函数默认的返回值是创建的对象(也就是实例),普通函数的返回值有return语句决定
- 构造函数的函数名与类名相同
15、请简述原型、原型链、(原型)继承
什么是原型?
任何对象实例都有一个原型,也叫原型对象,这个原型对象由对象的内置属性proto指向它的构造函数的prototype指向的对象,即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype。
什么是原型链?
原型链基本思想是利用利用原型让一个引用类型继承另一个引用类型的属性和方法。我们知道,每个构造函数都有一个原型对象,每个原型对象都有一个指向构造函数的指针,而实例又包含一个指向原型对象的内部指针
原型链的核心就是依赖对象的proto的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有proto指向了。
因为proto实质找的是prototype,所以我们只要找到这个链条上的构造函数的prototype。其中Obiect.prototype是没有proto属性的,它==null。
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数对象内部的指针。我们让原型对象(1)等于另一个原型对象(2),此时原型对象(2)将包含一个指向原型对象(1)的指针,再让原型对象(2)的实例等于原型对象(3),如此层层递进就构成了实例和原型的链条,这就是原型练得概念
什么是原型继承?
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数理想指针(constructor),而实例对象都包含一个指向原型对象的内部指针(proto)。如果让原型对象等于另一个原型对象的实例,此时的原型对象将包含一个指向另一个原型的指针(proto),另一个原型也包含着一个指向另一个构造函数的指针
(constructor)。假如另一个原型又是另一个类型的实例……这就构成了实例与原型的链条。也叫原型链
原型继承是js的一种继承方式,原型链作为实现继承的主要方法,其基本思路是利用原型让一个引用类型
继承另一个引用类型的属性和方法,
**原型继承:**利用原型中的成员可以被和其他相关的对象共享这一特性,可以实现继承,这种实现继承的方式,就叫原型继承。
16、Promise的理解
-
什么是Promise?我们用Promise来解决什么问题?
我们都知道,Promise是承诺的意思,承诺它过一段时间会给你一个结果。
Promise是一种解决异步操作编程的方案,相比回调函数和事件更合理和更强大。
从语法上讲,promise是一个对象,从它可以获取异步操作的信息。
-
Promise有三种状态
1、pending 初始状态也叫等待状态
2、fulfiled成功转态
3、rejected失败状态
-
Promise的两个特点
1、Promise对象的状态不受外界影响
2、Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可逆
-
Promise的三个缺点
1、无法取消Promise,一旦新建他就会立即执行,无法中途取消
2、如果不设置回调函数,Promise内部抛出的错误,不会映到外部
3、当处于pending(等待)状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
-
Promise是用来解决两个问题的
1、回调地狱,代码难以维护,尝尝第一个的函数的输出是第二个函数的输入这种现象
2、promise可以支持多并发的请求,获取并发请求中的数据这个
这个Promise可以解决异步的问题吗,本身不能说Promise是异步的
17、请简述async的用法
Async就是generation和Promise的语法糖,async就是将generation的 * 换成async,将yiled换成awite。
函数前必须加一个async,异步操作方法前加一个await关键字,意思就是等一下,执行完了再继续走,注意:await只能在async函数中运行,否则会报错
Promise如果返回的是一个错误的结果,如果沒有做异常处理就会报错,所以try…catch捕获一下异常就可以了。
18、一个页面从输入url到页面加载显示完成,这个过程都发生了什么?
分四个步骤
- 当发送一个URL请求时,不管这个URL是Web页面的URL还是Web页面上每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询。这能使浏览器获得请求对应的IP地址。
- 浏览器与远程Web服务器通过TCP三次握手协商来建立一个TCP/IPl连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在浏览器和服务端之间传递。该握手首先由客户端尝试建立起通信,然后服务器响应并接收客户端的请求,最后由客户端最后由客户端发出请求已被接受的报文。
- 一旦TCPIP连接建立,浏览器会通过该连接向远程服务器发送HTTP的GET请求。远程服务器找到资源并使用HTTP响应返回该资源
- 此时,Web服务器提供资源服务,客户端开始下载资源。
19、请简述js中 .call()与 .apply() 的区别。
- apply:调用一个对象的一个方法,用另一个对象替换当前对象。
- call:调用一个对象的一个方法,用另一个对象替当前对象
从定义中可以看出,call和apply都是调用对象的一个方法,用另一个对象替换当前对象,而不同之处在于传递的参数,apply最多只能有两个参数—新this对象和一个数组argArray,如果arg不是数组则会报错。
相同点:两个方法产生的作用是完全一样的。call,apply作用就是借用别人的方法来调用,就像调用自己的一样。
不同点:方法传递的参数不同。
20、为什么会造成跨域?请简述同源策略。
出现跨域问题的原因:
在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。在请求的过程中我们要想获取数据一般都是post/get请求,所以…跨域问题出现。
同源策略:
是由NetScape提出的一个著名的安全策略。所谓的同源,指的是协议,域名,端口号相同,浏览器出于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明授权的情况下,不能读写对方的资源。
21、请说说This的指向问题
在JavaScript中,this通常指向我们正在执行的函数本身,或者是指向该函数所属的对象。
- 全局的this → 指向的是Window
- 对象中的this → 指向其本身
- 事件中的this → 指向事件对象
22、什么是jsonp 工作原理是什么?他为什么不是真正的ajax?
jsonp其实就是一个跨域解决方案。
js跨域请求数据是不可以的,但是js跨域请求js脚本是可以的。
所以可以把要请求的数据封装成一个js语句,做一个方法的调用。
跨域请求js脚本可以得到此脚本。得到js脚本之后立即执行。
可以把数据作为参数传递到方法中。就可以获得数据。从而解决跨域问题。
jsonp原理(动态创建scrpit标签,回调函数)
浏览器在js请求中,是允许通过script标签的src跨域请求,可以在请求的结果中添加回调方法名,在请求页面中定义方法,就可以获取到跨域请求的数据。
为什么不是真正的ajax?
- ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也不一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
- 但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取本页面,而jsonp的核心则是动态添加
< script>标签来调用服务器提供的js脚本。
- 所以说ajsx和jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
- 还有就是,jsonp是一种方式或者说非强制协议,如同ajax一样,他也不一定非要json格式来传递数据,如果你愿意,字符串也行,只不过这样不利于jsonp提供公开服务。
23、请说出简单的类与继承
创建类有三种:
- 使用function和this关键字
- 原型对象 用prototype和this关键字
- 使用Object。create()方法构造
继承有六种:
- 原型继承
- 借用构造函数继承
- 组合继承
- 原型式继承
- 寄生式继承
- 寄生组合式继承
24、简述同步与异步的区别,阻塞与非阻塞的区别
同步(阻塞的)
异步(非阻塞的)
比如:同步,你在看电影,到吃饭时间了,但是你的电影没有看完,你就等电影看完再去吃饭
异步:你在看电影,到吃饭时间了,但是你的电影虽然没有看完,但是你的点了外卖一边吃一边看
同步(阻塞)异步(非阻塞)这两个关注的是程序在等待调用结果时的状态
25、为什么js是弱类型语言?
弱类型语言实现相当于强类型语言来说,在强类型语言中,变量类型有很多种,比如int char float Boolean 不同类型的相互转换有时需要强制转换,而javascript只有一种类型var,为变量赋值时会自动判断类型并转换,所以是弱类型语言。
26、箭头函数与普通函数的区别
- 箭头函数是匿名函数,不能作为构造函数,不能使用new
- 箭头函数不能绑定arguments,要用rest参数来解决
- 箭头函数没有原型属性
- 箭头函数的this永远指向其上下文的this
- 箭头函数不能绑定this,会捕获其所在的上下文的this值,作为自己的this值
27、For循环与map循环的区别?
For遍历对象自身的和继承可枚举的属性,也就是说会包括那些原型链上的属性
Map方法不会对空数组进行检测,map会返回一个新数组,不会对原数组产生影响
28、原型和继承,prototype,call和apply继承的区别(第一个参数是相同的,第二个的区别在哪)
apply() 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call() 方法第一个参数与apply() 方法相同,但传递给函数的参数必须列举出来。
29、深浅拷贝是什么?如何实现?
- 深拷贝:指针赋值,并且内容拷贝。
- 浅拷贝:只是简单地指针赋值。
- 数组浅拷贝:如果是数组,可以使用数组的一些方法实现:slice(),concat()返回一个新数组的特性实现拷贝。用扩展运算符spread实现
- 数组深拷贝:JSON.parse(JSON.stringify())不仅适用于数组还适用于对象。不能拷贝函数,undefined,symbol。
30、什么时候用深拷贝/浅拷贝?
无论深浅,都是需要的,当深拷贝发生时通常表明存在着一个聚合关系,当浅拷贝发生时,通常表明存在着相识关系
举个简单的例子:当实现一个组合模式Composite Pattern时通常都会实现深拷贝
当实现一个观察者模式Observe Pattern时,就需要浅拷贝
31、什么是js内存泄露?
内存泄漏是指一块被分配的内存既不能使用也不能回收,知道浏览器进程结束
释放内存的方法:赋值为null
32、什么是csrf攻击?
csrf(跨站点请求伪造)攻击者在用户已经登录目标网站之后,有使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份再攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的
33、预加载和懒加载的区别,预加载在什么时候加载合适?
预加载是指页面完成加载之前,提前将所需资源下载,之后使用的时候从缓存中调用
懒加载是延迟加载,按照一定的条件或者需求等到满足条件的时候在加载对应的资源。
两者主要区别是一个是提前加载,一个是延迟加载甚至不加载。 懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
34、谈谈Js的函数节流和函数防抖的区别
- 函数节流是指一定时间内js方法只执行一次。
- 函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次
- 函数节流是声明一个变量当标志位,记录当前代码是否在执行,如果正在执行,取消这次方法执行,直return,如果空闲,正常触发方法执行
- 函数防抖是需要一个延时器来辅助实现,延迟执行需要执行的代码,如果方法多次触发,把上次记录的延迟执行代码用cleartimeout清除掉,重新开始,如果计时完毕,没有方法来访问触发,则执行代码。