新闻| 文章| 资讯| 行情| 企业| wap手机版| article文章| 首页|会员中心|保存桌面|手机浏览
普通会员

易达信息科技

企业列表
新闻列表
推荐企业新闻
联系方式
  • 联系人:依依
友情链接
  • 暂无链接
首页 > 新闻中心 > 面试宝典:25个最经典的JavaScript面试题及答案
新闻中心
面试宝典:25个最经典的JavaScript面试题及答案
发布时间:2024-11-22        浏览次数:8        返回列表

1.使用  来确定  是否是对象的潜在陷阱是什么?如何避免这个陷阱?

面试宝典:25个最经典的Javas<em></em>cript面试题及答案

尽管  是检查  是否对象的可靠方法,令人惊讶的是在Javascript中  也被认为是对象!

因此,令大多数开发人员惊讶的是,下面的代码将输出  (而不是) 到控制台:

只要清楚这一点,同时检查  是否为 ,就可以很容易地避免问题:

要答全问题,还有其他两件事情值得注意:

首先,上述解决方案将返回 ,当  是一个函数的时候。在大多数情况下,这是期望行为,但当你也想对函数返回  的话,你可以修改上面的解决方案为:

第二,上述解决方案将返回 ,当  是一个数组(例如,当 )的时候。在大多数情况下,这是期望行为,因为数组是真正的对象,但当你也想对数组返回  时,你可以修改上面的解决方案为:

或者,如果你使用jQuery的话:

由于  和  都定义在函数的封闭范围内,并且都始于 关键字,大多数Javascript开发人员期望  和  在上面的例子中都是undefined。

然而,事实并非如此。这里的问题是,大多数开发人员将语句  错误地理解为是以下声明的简写:

但事实上, 实际是以下声明的简写:

因此(如果你不使用严格模式的话),该代码段的输出是:

但是,  如何才能被定义在封闭函数的范围之外呢?是的,既然语句  是语句  和 的简写,  最终成为了一个全局变量(因为它没有前缀  关键字),因此仍然在范围内甚至封闭函数之外。

需要注意的是,在严格模式下(即使用 ),语句 将生成的运行时错误,从而避免任何否则可能会导致的headfakes /bug。 (还是你为什么应该理所当然地在代码中使用  的最好例子!)

上面的代码将输出以下内容到控制台:

在外部函数中,  和 两者都指向了 ,因此两者都可以正确地引用和访问 。

在内部函数中,  不再指向 。其结果是, 没有在内部函数中被定义,相反,指向到本地的变量 保持在范围内,并且可以访问。 (在ECMA 5之前,在内部函数中的 将指向全局的  对象;反之,因为作为ECMA 5,内部函数中的功能 是未定义的。)

这是一个越来越普遍的做法,被许多流行的Javascript库(jQuery,Node.js等)采用。这种技术创建了一个围绕文件全部内容的

这种技术的另一个特点是,允许一个易于引用的(假设更短的)别名用于全局变量。这通常用于,例如,jQuery插件中。jQuery允许你使用,来禁用  引用到jQuery命名空间。在完成这项工作之后,你的代码仍然可以使用 利用这种闭包技术,如下所示:

对于这个问题,既简要又最重要的答案是, 是一种在Javascript代码运行时自动实行更严格解析和错误处理的方法。那些被忽略或默默失败了的代码错误,会产生错误或抛出异常。通常而言,这是一个很好的做法。

严格模式的一些主要优点包括:

出人意料的是,这两个函数返回的内容并不相同。更确切地说是:

将产生:

这不仅是令人惊讶,而且特别让人困惑的是, 返回undefined却没有任何错误抛出。

原因与这样一个事实有关,即分号在Javascript中是一个可选项(尽管省略它们通常是非常糟糕的形式)。其结果就是,当碰到 中包含 语句的代码行(代码行上没有其他任何代码),分号会立即自动插入到返回语句之后。

也不会抛出错误,因为代码的其余部分是完全有效的,即使它没有得到调用或做任何事情(相当于它就是是一个未使用的代码块,定义了等同于字符串 的属性 )。

这种行为也支持放置左括号于Javascript代码行的末尾,而不是新代码行开头的约定。正如这里所示,这不仅仅只是Javascript中的一个风格偏好。

 属性代表一个“不是数字”的值。这个特殊的值是因为运算不能执行而导致的,不能执行的原因要么是因为其中的运算对象之一非数字(例如, ),要么是因为运算的结果非数字(例如,除数为零)。

虽然这看上去很简单,但  有一些令人惊讶的特点,如果你不知道它们的话,可能会导致令人头痛的bug。

首先,虽然  意味着“不是数字”,但是它的类型,不管你信不信,是 :

此外,  和任何东西比较——甚至是它自己本身!——结果是false:

一种半可靠的方法来测试一个数字是否等于 NaN,是使用内置函数 ,但即使使用  依然并非是一个完美的解决方案。

一个更好的解决办法是使用 ,如果值等于NaN,只会产生true。另外,ES6提供了一个新的  函数,这是一个不同的函数,并且比老的全局  函数更可靠。

一个稍微有点编程基础的回答是:“你不能确定。可能会输出“0.3”和“true”,也可能不会。Javascript中的数字和浮点精度的处理相同,因此,可能不会总是产生预期的结果。“

以上所提供的例子就是一个演示了这个问题的典型例子。但出人意料的是,它会输出:

这可能听起来是小菜一碟,但事实上,这很琐碎,因为ECMAscript 6引入了一个新的正以此为目的  函数。然而,之前的ECMAscript 6,会更复杂一点,因为没有提供类似的  方法。

问题是,在ECMAscript规格说明中,整数只概念上存在:即,数字值总是存储为浮点值。

考虑到这一点,最简单又最干净的ECMAscript6之前的解决方法(同时也非常稳健地返回  ,即使一个非数字的值,如字符串或  ,被传递给函数)如下:

下面的解决方法也是可行的,虽然不如上面那个方法优雅:

请注意  和  在上面的实现中等同于 。

或:

相当普遍的一个不正确的解决方案是:

虽然这个以 函数为基础的方法在  取许多值时都能工作良好,但一旦  取值相当大的时候,就会无法正常工作。问题在于  在解析数字之前强制其第一个参数到字符串。因此,一旦数目变得足够大,它的字符串就会表达为指数形式(例如, )。因此, 函数就会去解析 ,但当到达 字符串的时候,就会停止解析,因此只会返回值 。注意:

序号如下:

让我们先来解释比较明显而易见的那部分:

好的。但是,既然  是0毫秒延迟之后输出的,那么是否意味着它是立即输出的呢?如果是的话,那么它是不是应该在  之前输出,既然  是在第二行输出的?

要回答这个问题,你需要正确理解Javascript的事件和时间设置。

浏览器有一个事件循环,会检查事件队列和处理未完成的事件。例如,如果时间发生在后台(例如,脚本的  事件)时,浏览器正忙(例如,处理一个 ),那么事件会添加到队列中。当onclick处理程序完成后,检查队列,然后处理该事件(例如,执行  脚本)。

同样的,  也会把其引用的函数的执行放到事件队列中,如果浏览器正忙的话。

当的第二个参数为0的时候,它的意思是“尽快”执行指定的函数。具体而言,函数的执行会放置在事件队列的下一个计时器开始。但是请注意,这不是立即执行:函数不会被执行除非下一个计时器开始。这就是为什么在上述的例子中,调用  发生在调用  之前(因为调用  是通过setTimeout被调用的,因此会稍微延迟)。

下面这个函数在  是回文结构的时候返回true,否则,返回false。

例如:

12.写一个 方法,在使用下面任一语法调用时,都可以正常工作。

(至少)有两种方法可以做到:

方法1

在Javascript中,函数可以提供到  对象的访问, 对象提供传递到函数的实际参数的访问。这使我们能够使用  属性来确定在运行时传递给函数的参数数量。

如果传递两个参数,那么只需加在一起,并返回。

否则,我们假设它被以 这样的形式调用,所以我们返回一个匿名函数,这个匿名函数合并了传递到 的参数和传递给匿名函数的参数。

方法2

当调用一个函数的时候,Javascript不要求参数的数目匹配函数定义中的参数数量。如果传递的参数数量大于函数定义中参数数量,那么多余参数将简单地被忽略。另一方面,如果传递的参数数量小于函数定义中的参数数量,那么缺少的参数在函数中被引用时将会给一个 值。所以,在上面的例子中,简单地检查第2个参数是否未定义,就可以相应地确定函数被调用以及进行的方式。

(a)当用户点击“Button 4”的时候会输出什么到控制台,为什么?(b)提供一个或多个备用的可按预期工作的实现方案。

(a)无论用户点击什么按钮,数字5将总会输出到控制台。这是因为,当  方法被调用(对于任何按钮)的时候,  循环已经结束,变量  已经获得了5的值。(面试者如果能够谈一谈有关如何执行上下文,可变对象,激活对象和内部“范围”属性贡有助于闭包行为,则可以加分)。

(b)要让代码工作的关键是,通过传递到一个新创建的函数对象,在每次传递通过  循环时,捕捉到  值。下面是三种可能实现的方法:

或者,你可以封装全部调用到在新匿名函数中的  :

也可以调用数组对象的本地  方法来替代  循环:

输出结果是:

 和  在上述代码执行之后,两者相同了,原因是:

这里有几个侧面点有时候会让你在回答这个问题时,阴沟里翻船:

传递数组到另一个数组的  方法会让整个数组作为单个元素映射到数组的末端。其结果是,语句  在其整体中添加  作为一个单一的元素到  的末端(也就是说,它并没有连接两个数组,连接数组是  方法的目的)。

和Python一样,Javascript标榜数组方法调用中的负数下标,例如  可作为引用数组末尾元素的方法:例如,-1下标表示数组中的最后一个元素,等等。

上面的代码将输出以下内容到控制台:

原因是…

这里的根本问题是,Javascript(ECMAscript)是一种弱类型语言,它可对值进行自动类型转换,以适应正在执行的操作。让我们通过上面的例子来说明这是如何做到的。

例1: 输出: 说明:  是执行的第一个操作。由于其中一个运算对象()是字符串,Javascript会假设它需要执行字符串连接,因此,会将  的类型转换为 , 结果就是 。然后,  就是 。

例2:  输出:  说明:根据运算的顺序,要执行的第一个运算是 (第一个  前面的额外  被视为一元运算符)。因此,Javascript将  的类型转换为数字,然后应用一元  号(即,将其视为一个正数)。其结果是,接下来的运算就是  ,这当然是 。然后我们需要在一个数字和一个字符串之间进行运算(即,  和 ),同样的,Javascript会将数值类型转换为字符串,并执行字符串的连接,产生 。

例3:  输出:   说明:这里的解释和前一个例子相同,除了此处的一元运算符是  而不是 。先是  变为 ,然后当应用  时又变为了  ,然后将其与 相加,结果为 ,再将其转换为字符串,连接最后的  运算对象,得到 。

例4:  输出:  说明:虽然第一个运算对象 因为前缀的一元  运算符类型转换为数值,但又立即转换回字符串,当连接到第二个运算对象  的时候,然后又和最后的运算对象 连接,产生了字符串 。

例5:  输出:  说明:由于运算符   不能被应用于字符串,并且  和  都不能转换成数值,因此,的结果是 ,然后再和字符串  连接,得到  。

例6:  输出:  说明:参见前一个例子,  结果为 。但是,应用任何运算符到NaN与其他任何的数字运算对象,结果仍然是 。

潜在的堆栈溢出可以通过修改 函数避免:

堆栈溢出之所以会被消除,是因为事件循环操纵了递归,而不是调用堆栈。当  运行时,如果 不为空,timeout函数()就会被推到事件队列,该函数退出,因此就清空调用堆栈。当事件队列运行其timeout事件,且进行到下一个  时,定时器被设置为再次调用 。因此,该方法从头到尾都没有直接的递归调用,所以无论迭代次数的多少,调用堆栈保持清空的状态。

闭包是一个可以访问外部(封闭)函数作用域链中的变量的内部函数。闭包可以访问三种范围中的变量:这三个范围具体为:(1)自己范围内的变量,(2)封闭函数范围内的变量,以及(3)全局变量。

下面是一个简单的例子:

在上面的例子中,来自于 , 和全局命名空间的变量都在 的范围内。因此,上面的代码将输出如下:

解释你的答案。闭包在这里能起什么作用?

上面的代码不会按预期显示值0,1,2,3,和4,而是会显示5,5,5,5,和5。

原因是,在循环中执行的每个函数将整个循环完成之后被执行,因此,将会引用存储在 中的最后一个值,那就是5。

闭包可以通过为每次迭代创建一个唯一的范围,存储范围内变量的每个唯一的值,来防止这个问题,如下:

这就会按预期输出0,1,2,3,和4到控制台。

并解释。

该代码将输出:

在Javascript中,  和 都是逻辑运算符,用于在从左至右计算时,返回第一个可完全确定的“逻辑值”。

或(  )运算符。在形如 的表达式中,首先计算 并将其解释执行为一个布尔值。如果这个布尔值,那么返回(1),不再计算 ,因为“或”的条件已经满足。如果这个布尔值为,那么我们仍然不能知道 是真是假,直到我们计算 ,并且也把它解释执行为一个布尔值。

因此,  的计算结果为true(1),同理计算。

与( )运算符。在形如 的表达式中,首先计算 并将其解释执行为一个布尔值。如果这个布尔值为 ,那么返回 (0),不再计算 ,因为“与”的条件已经失败。如果这个布尔值为,但是,我们仍然不知道  是真是假,直到我们去计算 ,并且也把它解释执行为一个布尔值。

不过,关于 运算符有趣的地方在于,当一个表达式计算为“true”的时候,那么就返回表达式本身。这很好,虽然它在逻辑表达式方面计算为“真”,但如果你希望的话也可用于返回该值。这就解释了为什么,有些令人奇怪的是, 返回 (而不是你以为的可能返回  或 )。

代码将输出:

在Javascript中,有两种等式运算符。三个等于运算符  的作用类似传统的等于运算符:如果两侧的表达式有着相同的类型和相同的值,那么计算结果为true。而双等于运算符,会只强制比较它们的值。因此,总体上而言,使用 而不是 的做法更好。 vs 亦是同理。

这段代码将输出 (而不是 )。

原因为:当设置对象属性时,Javascript会暗中字符串化参数值。在这种情况下,由于  和 都是对象,因此它们都将被转换为。结果就是, 和均相当于 ,并可以互换使用。因此,设置或引用 和设置或引用 完全相同。

并解释你的答案。

代码将输出10!的值(即10!或3628800)。

原因是:

命名函数 递归地调用本身,当调用 的时候,只简单地返回。下面就是它的调用过程:

23.请看下面的代码段。控制台将输出什么,为什么?

控制台将输出 ,即使从来没有在函数内部设置过的值。原因是:

正如我们在Javascript招聘指南中解释过的那样,闭包是一个函数,连同在闭包创建的时候,其范围内的所有变量或函数一起。在Javascript中,闭包是作为一个“内部函数”实施的:即,另一个函数主体内定义的函数。闭包的一个重要特征是,内部函数仍然有权访问外部函数的变量。

因此,在本例中,由于 未在函数内部中定义,因此在外部函数范围中搜索定义的变量 ,且被发现具有的值。

代码有什么问题,以及应该如何修复。

代码将输出:

第一个 之所以输出 ,是因为我们正在从 对象提取方法,所以调用了全局上下文中(即窗口对象)的 ,而在此全局上下文中, 属性不存在。

其中一种修复 函数的方法如下:

此函数的参数为:

访问树(DOM)的所有元素是经典的深度优先搜索算法应用。下面是一个示范的解决方案:

译文链接:http://www.codeceo.com/article/25-essential-javascript-interview-questions.html