JavaScript 和 jQuery 高频面试题

JavaScript

数据类型

基本类型:Number,String,Boolean,Null,Undefined,Symbol(ES6)
引用类型:Array,Functionm,Object

基本类型和引用类型的区别

引用类型值保存在堆里,基本类型是存放在栈里
引用类型值可添加属性和方法,而基本类型值则不可以

判断类型方式

typeof
instanceof
Object.prototype.toString.call()

栈和堆的区别

栈由编译器自动分配释放空间,堆一般由程序员分配释放
栈存放在一级缓存中,调用完毕立即释放;堆则是在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定

数组常用方法
  • 改变原数组

shift:删除第一个元素
unshift:向数组开头添加元素
pop:删除最后一个元素
push:向数组末尾添加元素
reverse:数组倒序排序
sort:数组正序排序
splice: splice(start,length,item)删,增,替换数组元素

  • 不改变原数组

concat:连接多个数组
join:将数组所有元素以字符分隔
slice:slice(start,end),切割数组
map,filter,some,every等不改变原数组

数组排序

reverse()倒序
sort()正序
冒泡排序

JavaScript 和 jQuery 高频面试题

数组去重

indexOf() 用for循环遍历数组,把等于-1的值push进新建的空数组里
es6的set()方法

JavaScript 和 jQuery 高频面试题

浅拷贝与深拷贝

深拷贝和浅拷贝只针引用类型(Object、Array)的数据
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共享同一内存,修改新对象会改变原对象
深拷贝则另外创造个一模一样的对象,新旧对象不共享内存,修改新对象不会改到原对象

  • 浅拷贝实现方法

Object.assign() // 注意,当object只有一层结构,是深拷贝
Array.prototype.concat()
Array.prototype.slice()

  • 深拷贝实现方法

JSON.parse(JSON.stringify())
递归法,for循环遍历对象、数组直到里边都是基本数据类型,然后再去复制

  • JSON.stringify()实现深拷贝的缺点

如obj里有时间对象,则JSON.stringify(序列化)再JSON.parse(反序列化)后,时间对象将变成字符串形式,而不是对象形式
如obj里有正则(RegExp)、Error对象,则序列化后只得到空对象
如obj里有函数,undefined,则序列化后会丢失
如obj里有NaN、正无穷(Infinity)和负无穷(-Infinity),则序列化后会变成null

null,undefined的区别

null用来表示尚未存在的对象
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义

函数声明与函数表达式

在js中,解析器会率先读取函数声明,并使其在执行任何代码前可用(可访问)
而函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行

函数对象

在JS中,函数即对象

原型对象

定义函数对象时,会包含一个预定义属性prototype,称为原型对象

proto

创建对象时,会有个[[proto]]内置属性,用于指向创建它的函数对象的prototype,prototype也有[[proto]]属性,在不断指向中,形成了原型链

原型链的终点

原型链终点是null

原型链终点为什么是null

原型链上所有节点都是对象,不能是字符串、数字、布尔值等原始类型
另外,规范要求原型链必须是有限长度

new操作符具体做了什么

创建空对象,this引用该对象,同时继承该对象的原型
属性和方法被加入到this引用的对象中

this指向问题

当没有被对象调用时,指向window
当被对象调用时,指向调用他的对象
当实例化对象就在对象中时,指向该实例化对象

判断空对象方法
  1. JSON.stringify(obj)
    // 判断JSON.stringify(data) == “{}”
  2. Object.keys(obj)
    // 返回自身的可枚举属性
    // 判断Object.keys(data).length === 0
闭包

闭包就是能够读取其他函数内部变量的函数

闭包优点

将变量长期保存,不被垃圾回收机制回收
避免全局变量的污染
安全性提高

闭包缺点

容易造成内存泄漏

闭包应用场景

封装私有变量
通过闭包实现setTimeout传参
作为回调函数绑定到事件

常见内存泄漏

闭包
全局变量,相当于挂载到 window 对象上
被遗忘的定时器和回调函数

垃圾回收机制

标记清除
引用计数

事件冒泡

当元素接收事件时,会把接收的事件传递给自己的父级,层层传递直到window

阻止事件冒泡

IE浏览器: e.cancelBubble = true
其他: e.stopPropagation()

事件捕获

用addEventListener监听目标元素事件

阻止默认事件

return false
ev.preventDefault()

事件委托原理,及优缺点
  • 原理为事件冒泡机制

  • 优点

可大量节省内存占用,减少事件注册
可实现当新增子对象时,无需再对其事件绑定,对于动态内容部分尤为合适

  • 缺点

可能会出现事件误判,把本不应用触发事件的被绑上了事件

事件循环

Javascriprt为单线程。单线程的缺点是所有任务需排队,后一个任务要等前一个任务执行完毕,这样耗时太久,于是js所有任务分为两种:同步任务,异步任务
JS引擎将所有任务按类添加到宏任务、微任务两个队列,首先在宏任务队列中取出第一个任务,执行完毕后,再把微任务队列中所有任务按序执行完,之后再取宏任务,周而复始,直至两个队列的任务都取完,过程就叫事件循环

宏任务和微任务

宏任务:setTimeout,setInterval
微任务:Promise,process.nextTick

jQuery

jQuery 库中的 $() 是什么?

$ () 函数是 jQuery() 函数的别称,乍一看这很怪异,还使 jQuery 代码晦涩难懂。一旦你适应了,你会爱上它的简洁。$() 函数用于将任何对象包裹成 jQuery 对象,接着你就被允许调用定义在 jQuery 对象上的多个不同方法。你甚至可以将一个选择器字符串传入 $() 函数,它会返回一个包含所有匹配的 DOM 元素数组的 jQuery 对象。这个问题我已经见过好几次被提及,尽管它非常基础,它经常被用来区分一个开发人员是否了解 jQuery。

网页上有 5 个 < div> 元素,如何使用 jQuery来选择它们?

另一个重要的 jQuery 问题是基于选择器的。jQuery 支持不同类型的选择器,例如 ID 选择器、class 选择器、标签选择器。鉴于这个问题没提到 ID 和 class,你可以用标签选择器来选择所有的 div 元素。jQuery 代码:$(“div”),这样会返回一个包含所有 5 个 div 标签的 jQuery 对象。

jQuery 里的 ID 选择器和 class 选择器有何不同?

如果你用过 CSS,你也许就知道 ID 选择器和 class 选择器之间的差异,jQuery 也同样如此。ID 选择器使用 ID 来选择元素,比如 #element1,而 class 选择器使用 CSS class 来选择元素。当你只需要选择一个元素时,使用 ID 选择器,而如果你想要选择一组具有相同 CSS class 的元素,就要用 class 选择器。在面试过程中,你有很大几率会被要求使用 ID 选择器和 class 选择器来写代码。下面的 jQuery 代码使用了 ID 选择器和 class 选择器:
$(’#LoginTextBox’) // Returns element wrapped as jQuery object with id=‘LoginTextBox’
$(’.active’) // Returns all elements with CSS class active.

正如你所见,从语法角度来说,ID 选择器和 class 选择器的另一个不同之处是,前者用字符”#”而后者用字符”.”

如何在点击一个按钮时使用 jQuery 隐藏一个图片?

这是一个事件处理问题。jQuery为按钮点击之类的事件提供了很好的支持。你可以通过以下代码去隐藏一个通过ID或class定位到的图片。你需要知道如何为按钮设置事件并执行hide() 方法,代码如下所示:
$(’#ButtonToClick’).click(function(){
$(’#ImageToHide’).hide();
});

我喜欢这个问题,因为很贴近实际使用,代码也不复杂。

$(document).ready() 是个什么函数?为什么要用它?(answer)

这个问题很重要,并且常常被问到。 ready() 函数用于在文档进入ready状态时执行代码。当DOM 完全加载(例如HTML被完全解析DOM树构建完成时),jQuery允许你执行代码。使用$(document).ready()的最大好处在于它适用于所有浏览器,jQuery帮你解决了跨浏览器的难题。需要进一步了解的用户可以点击 answer链接查看详细讨论。

JavaScript window.onload 事件和 jQuery ready 函数有何不同?

这个问答是紧接着上一个的。JavaScript window.onload 事件和 jQuery ready 函数之间的主要区别是,前者除了要等待 DOM 被创建还要等到包括大型图片、音频、视频在内的所有外部资源都完全加载。如果加载图片和媒体内容花费了大量时间,用户就会感受到定义在 window.onload 事件上的代码在执行时有明显的延迟。
另一方面,jQuery ready() 函数只需对 DOM 树的等待,而无需对图像或外部资源加载的等待,从而执行起来更快。使用 jQuery $(document).ready() 的另一个优势是你可以在网页里多次使用它,浏览器会按它们在 HTML 页面里出现的顺序执行它们,相反对于 onload 技术而言,只能在单一函数里使用。鉴于这个好处,用 jQuery ready() 函数比用 JavaScript window.onload 事件要更好些。

如何找到所有 HTML select 标签的选中项?

这是面试里比较棘手的 jQuery 问题之一。这是个基础的问题,但是别期望每个 jQuery 初学者都知道它。你能用下面的 jQuery 选择器获取所有具备 multiple=true 的 < select > 标签的选中项:
$(’[name=NameOfSelectedTag] :selected’)
这段代码结合使用了属性选择器和 :selected 选择器,结果只返回被选中的选项。你可按需修改它,比如用 id 属性而不是 name 属性来获取 < select> 标签。

jQuery 里的 each() 是什么函数?你是如何使用它的?

each() 函数就像是 Java 里的一个 Iterator,它允许你遍历一个元素集合。你可以传一个函数给 each() 方法,被调用的 jQuery 对象会在其每个元素上执行传入的函数。有时这个问题会紧接着上面一个问题,举个例子,如何在 alert 框里显示所有选中项。我们可以用上面的选择器代码找出所有选中项,然后我们在 alert 框中用 each() 方法来一个个打印它们,代码如下:
$ (’[name=NameOfSelectedTag] :selected’).each(function(selected) {
alert($(selected).text());
});

其中 text() 方法返回选项的文本。

你是如何将一个 HTML 元素添加到 DOM 树中的?

你可以用 jQuery 方法 appendTo() 将一个 HTML 元素添加到 DOM 树中。这是 jQuery 提供的众多操控 DOM 的方法中的一个。你可以通过 appendTo() 方法在指定的 DOM 元素末尾添加一个现存的元素或者一个新的 HTML 元素。

你能用 jQuery 代码选择所有在段落内部的超链接吗?

这是另一个关于选择器的 jQuery 面试题。就像其他问题那样,只需一行 jQuery 代码就能搞定。你可以使用下面这个 jQuery 代码片段来选择所有嵌套在段落(< p>标签)内部的超链接(< a>标签)……

$(this) 和 this 关键字在 jQuery 中有何不同?

这对于很多 jQuery 初学者来说是一个棘手的问题,其实是个简单的问题。$(this) 返回一个 jQuery 对象,你可以对它调用多个 jQuery 方法,比如用 text() 获取文本,用val() 获取值等等。而 this 代表当前元素,它是 JavaScript 关键词中的一个,表示上下文中的当前 DOM 元素。你不能对它调用 jQuery 方法,直到它被 $() 函数包裹,例如 $(this)。

你如何使用jQuery来提取一个HTML 标记的属性 例如. 链接的href?

attr() 方法被用来提取任意一个HTML元素的一个属性的值. 你首先需要利用jQuery选择及选取到所有的链接或者一个特定的链接,然后你可以应用attr()方法来获得他们的href属性的值。下面的代码会找到页面中所有的链接并返回href值:
$ (‘a’).each(function(){
alert( $ (this).attr(‘href’));
});

你如何使用jQuery设置一个属性值?

前面这个问题之后额外的一个后续问题是,attr()方法和jQuery中的其它方法一样,能力不止一样. 如果你在调用attr()的同时带上一个值 例如. attr(name, value), 这里name是属性的名称,value是属性的新值。

jQuery中 detach() 和 remove() 方法的区别是什么?

尽管 detach() 和 remove() 方法都被用来移除一个DOM元素, 两者之间的主要不同在于 detach() 会保持对过去被解除元素的跟踪, 因此它可以被取消解除, 而 remove() 方法则会保持过去被移除对象的引用. 你也还可以看看 用来向DOM中添加元素的 appendTo() 方法.

你如何利用jQuery来向一个元素中添加和移除CSS类?

通过利用 addClass() 和 removeClass() 这两个 jQuery 方法。动态的改变元素的class属性可以很简单例如. 使用类“.active"来标记它们的未**和**状态,等等.

使用 CDN 加载 jQuery 库的主要优势是什么 ? (答案)

这是一个稍微高级点儿的jQuery问题。好吧,除了报错节省服务器带宽以及更快的下载速度这许多的好处之外, 最重要的是,如果浏览器已经从同一个CDN下载类相同的 jQuery 版本, 那么它就不会再去下载它一次. 因此今时今日,许多公共的网站都将jQuery用于用户交互和动画, 如果浏览器已经有了下载好的jQuery库,网站就能有非常好的展示机会。

jQuery.get() 和 jQuery.ajax() 方法之间的区别是什么?

ajax() 方法更强大,更具可配置性, 让你可以指定等待多久,以及如何处理错误。get() 方法是一个只获取一些数据的专门化方法。

jQuery 中的方法链是什么?使用方法链有什么好处?

方法链是对一个方法返回的结果调用另一个方法,这使得代码简洁明了,同时由于只对 DOM 进行了一轮查找,性能方面更加出色。

你要是在一个 jQuery 事件处理程序里返回了 false 会怎样?

这通常用于阻止事件向上冒泡。

哪种方式更高效:document.getElementbyId(“myId”) 还是 $("#myId")?

第一种,因为它直接调用了 JavaScript 引擎。