好程序员Java教程分享JavaScript面试问题及答案(一)

代码揽虹客
• 阅读 98

好程序员Java教程分享JavaScript面试问题及答案(一)
  1.使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个陷阱?
  尽管 typeof bar === "object" 是检查 bar 是否对象的可靠方法,令人惊讶的是在JavaScript中 null 也被认为是对象!
  因此,令大多数开发人员惊讶的是,下面的代码将输出 true (而不是false) 到控制台:
  var bar = null;console.log(typeof bar === "object"); // logs true!
  只要清楚这一点,同时检查 bar 是否为 null,就可以很容易地避免问题:
  console.log((bar !== null) && (typeof bar === "object")); // logs false
  要答全问题,还有其他两件事情值得注意:
  首先,上述解决方案将返回 false,当 bar 是一个函数的时候。在大多数情况下,这是期望行为,但当你也想对函数返回 true 的话,你可以修改上面的解决方案为:
  console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function")));
  第二,上述解决方案将返回 true,当 bar 是一个数组(例如,当 var bar = [];)的时候。在大多数情况下,这是期望行为,因为数组是真正的对象,但当你也想对数组返回 false 时,你可以修改上面的解决方案为:
  console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]"));
  或者,如果你使用jQuery的话:
  console.log((bar !== null) && (typeof bar === "object") && (! $.isArray(bar)));
  2.下面的代码将输出什么到控制台,为什么?
  (function(){ var a = b = 3;
  })();console.log("a defined? " + (typeof a !== 'undefined'));console.log("b defined? " + (typeof b !== 'undefined'));
  由于 a 和 b 都定义在函数的封闭范围内,并且都始于 var关键字,大多数JavaScript开发人员期望 typeof a 和 typeof b 在上面的例子中都是undefined。
  然而,事实并非如此。这里的问题是,大多数开发人员将语句 var a = b = 3; 错误地理解为是以下声明的简写:
  var b = 3;var a = b;
  但事实上,var a = b = 3; 实际是以下声明的简写:
  b = 3;var a = b;
  因此(如果你不使用严格模式的话),该代码段的输出是:
  a defined? falseb defined? true
  但是, b 如何才能被定义在封闭函数的范围之外呢?是的,既然语句 var a = b = 3; 是语句 b = 3; 和 var a = b;的简写, b 终成为了一个全局变量(因为它没有前缀 var 关键字),因此仍然在范围内甚至封闭函数之外。
  需要注意的是,在严格模式下(即使用 use strict),语句var a = b = 3; 将生成ReferenceError: b is not defined的运行时错误,从而避免任何否则可能会导致的headfakes /bug。 (还是你为什么应该理所当然地在代码中使用 use strict 的好例子!)
  3.下面的代码将输出什么到控制台,为什么?
  var myObject = {
  foo: "bar",
  func: function() { var self = this; console.log("outer func: this.foo = " + this.foo); console.log("outer func: self.foo = " + self.foo);
  (function() { console.log("inner func: this.foo = " + this.foo); console.log("inner func: self.foo = " + self.foo);
  }());
  }
  };
  myObject.func();
  上面的代码将输出以下内容到控制台:
  outer func: this.foo = bar
  outer func: self.foo = bar
  inner func: this.foo = undefined
  inner func: self.foo = bar
  在外部函数中, this 和self 两者都指向了 myObject,因此两者都可以正确地引用和访问 foo。
  在内部函数中, this 不再指向 myObject。其结果是,this.foo 没有在内部函数中被定义,相反,指向到本地的变量self 保持在范围内,并且可以访问。 (在ECMA 5之前,在内部函数中的this 将指向全局的 window 对象;反之,因为作为ECMA 5,内部函数中的功能this 是未定义的。)
  4.封装JavaScript源文件的全部内容到一个函数块有什么意义及理由?
  这是一个越来越普遍的做法,被许多流行的JavaScript库(jQuery,Node.js等)采用。这种技术创建了一个围绕文件全部内容的闭包,也许是重要的是,创建了一个私有的命名空间,从而有助于避免不同JavaScript模块和库之间潜在的名称冲突。
  这种技术的另一个特点是,允许一个易于引用的(假设更短的)别名用于全局变量。这通常用于,例如,jQuery插件中。jQuery允许你使用jQuery.noConflict(),来禁用 $ 引用到jQuery命名空间。在完成这项工作之后,你的代码仍然可以使用$ 利用这种闭包技术,如下所示:
  (function($) { /* jQuery plugin code referencing $ */ } )(jQuery);
  5.在JavaScript源文件的开头包含 use strict 有什么意义和好处?
  对于这个问题,既简要又重要的答案是,use strict 是一种在JavaScript代码运行时自动实行更严格解析和错误处理的方法。那些被忽略或默默失败了的代码错误,会产生错误或抛出异常。通常而言,这是一个很好的做法。
  严格模式的一些主要优点包括:
  使调试更加容易。那些被忽略或默默失败了的代码错误,会产生错误或抛出异常,因此尽早提醒你代码中的问题,你才能更快地指引到它们的源代码。
  防止意外的全局变量。如果没有严格模式,将值分配给一个未声明的变量会自动创建该名称的全局变量。这是JavaScript中常见的错误之一。在严格模式下,这样做的话会抛出错误。
  消除 this 强制。如果没有严格模式,引用null或未定义的值到 this 值会自动强制到全局变量。这可能会导致许多令人头痛的问题和让人恨不得拔自己头发的bug。在严格模式下,引用 null或未定义的 this 值会抛出错误。
  不允许重复的属性名称或参数值。当检测到对象(例如,var object = {foo: "bar", foo: "baz"};)中重复命名的属性,或检测到函数中(例如,function foo(val1, val2, val1){})重复命名的参数时,严格模式会抛出错误,因此捕捉几乎可以肯定是代码中的bug可以避免浪费大量的跟踪时间。
  使eval() 更安全。在严格模式和非严格模式下,eval() 的行为方式有所不同。显而易见的是,在严格模式下,变量和声明在 eval() 语句内部的函数不会在包含范围内创建(它们会在非严格模式下的包含范围中被创建,这也是一个常见的问题源)。
  在 delete使用无效时抛出错误。delete操作符(用于从对象中删除属性)不能用在对象不可配置的属性上。当试图删除一个不可配置的属性时,非严格代码将默默地失败,而严格模式将在这样的情况下抛出异常。
  6.考虑以下两个函数。它们会返回相同的东西吗? 为什么相同或为什么不相同?
  function foo1(){ return {
  bar: "hello"
  };
  }function foo2(){ return
  {
  bar: "hello"
  };
  }
  出人意料的是,这两个函数返回的内容并不相同。更确切地说是:
  console.log("foo1 returns:");console.log(foo1());console.log("foo2 returns:");console.log(foo2());
  将产生:
  foo1 returns:Object {bar: "hello"}foo2 returns:undefined
  这不仅是令人惊讶,而且特别让人困惑的是, foo2()返回undefined却没有任何错误抛出。
  原因与这样一个事实有关,即分号在JavaScript中是一个可选项(尽管省略它们通常是非常糟糕的形式)。其结果就是,当碰到 foo2()中包含 return语句的代码行(代码行上没有其他任何代码),分号会立即自动插入到返回语句之后。
  也不会抛出错误,因为代码的其余部分是完全有效的,即使它没有得到调用或做任何事情(相当于它就是是一个未使用的代码块,定义了等同于字符串 "hello"的属性 bar)。
  这种行为也支持放置左括号于JavaScript代码行的末尾,而不是新代码行开头的约定。正如这里所示,这不仅仅只是JavaScript中的一个风格偏好。
  7. NaN 是什么?它的类型是什么?你如何可靠地测试一个值是否等于 NaN ?
  NaN 属性代表一个“不是数字”的值。这个特殊的值是因为运算不能执行而导致的,不能执行的原因要么是因为其中的运算对象之一非数字(例如, "abc" / 4),要么是因为运算的结果非数字(例如,除数为零)。
  虽然这看上去很简单,但 NaN 有一些令人惊讶的特点,如果你不知道它们的话,可能会导致令人头痛的bug。
  首先,虽然 NaN 意味着“不是数字”,但是它的类型,不管你信不信,是 Number:
  console.log(typeof NaN === "number"); // logs "true"
  此外, NaN 和任何东西比较——甚至是它自己本身!——结果是false:
  console.log(NaN === NaN); // logs "false"
  一种半可靠的方法来测试一个数字是否等于 NaN,是使用内置函数 isNaN(),但即使使用 isNaN() 依然并非是一个完美的解决方案。
  一个更好的解决办法是使用 value !== value,如果值等于NaN,只会产生true。另外,ES6提供了一个新的 Number.isNaN() 函数,这是一个不同的函数,并且比老的全局 isNaN() 函数更可靠。
  8.下列代码将输出什么?并解释原因。
  console.log(0.1 + 0.2);console.log(0.1 + 0.2 == 0.3);
  一个稍微有点编程基础的回答是:“你不能确定。可能会输出“0.3”和“true”,也可能不会。JavaScript中的数字和浮点精度的处理相同,因此,可能不会总是产生预期的结果。“
  以上所提供的例子就是一个演示了这个问题的典型例子。但出人意料的是,它会输出:
  0.30000000000000004false
  9.讨论写函数 isInteger(x) 的可能方法,用于确定x是否是整数。
  这可能听起来是小菜一碟,但事实上,这很琐碎,因为ECMAScript 6引入了一个新的正以此为目的 Number.isInteger() 函数。然而,之前的ECMAScript 6,会更复杂一点,因为没有提供类似的 Number.isInteger() 方法。
  问题是,在ECMAScript规格说明中,整数只概念上存在:即,数字值总是存储为浮点值。
  考虑到这一点,简单又干净的ECMAScript6之前的解决方法(同时也非常稳健地返回 false ,即使一个非数字的值,如字符串或 null ,被传递给函数)如下:
  function isInteger(x) { return (x^0) === x; }
  下面的解决方法也是可行的,虽然不如上面那个方法优雅:
  function isInteger(x) { return Math.round(x) === x; }
  请注意 Math.ceil() 和 Math.floor() 在上面的实现中等同于 Math.round()。
  或:
  function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0);
  相当普遍的一个不正确的解决方案是:
  function isInteger(x) { return parseInt(x, 10) === x; }
  虽然这个以 parseInt函数为基础的方法在 x 取许多值时都能工作良好,但一旦 x 取值相当大的时候,就会无法正常工作。问题在于 parseInt() 在解析数字之前强制其第一个参数到字符串。因此,一旦数目变得足够大,它的字符串就会表达为指数形式(例如, 1e+21)。因此,parseInt() 函数就会去解析 1e+21,但当到达 e字符串的时候,就会停止解析,因此只会返回值 1。注意:
  > String(1000000000000000000000)'1e+21'> parseInt(1000000000000000000000, 10)1> parseInt(1000000000000000000000, 10) === 1000000000000000000000false
  10.下列代码行1-4如何排序,使之能够在执行代码时输出到控制台? 为什么?
  (function() { console.log(1);
  setTimeout(function(){console.log(2)}, 1000);
  setTimeout(function(){console.log(3)}, 0);
  console.log(4);
  })();
  序号如下:
  1
  4
  3
  2
  让我们先来解释比较明显而易见的那部分:
  1 和 4之所以放在前面,是因为它们是通过简单调用 console.log() 而没有任何延迟输出的
  2 之所以放在 3的后面,是因为 2 是延迟了1000毫秒(即,1秒)之后输出的,而 3 是延迟了0毫秒之后输出的。
  好的。但是,既然 3 是0毫秒延迟之后输出的,那么是否意味着它是立即输出的呢?如果是的话,那么它是不是应该在 4 之前输出,既然 4 是在第二行输出的?
  要回答这个问题,你需要正确理解JavaScript的事件和时间设置。
  浏览器有一个事件循环,会检查事件队列和处理未完成的事件。例如,如果时间发生在后台(例如,脚本的 onload 事件)时,浏览器正忙(例如,处理一个 onclick),那么事件会添加到队列中。当onclick处理程序完成后,检查队列,然后处理该事件(例如,执行 onload 脚本)。
  同样的, setTimeout() 也会把其引用的函数的执行放到事件队列中,如果浏览器正忙的话。
  当setTimeout()的第二个参数为0的时候,它的意思是“尽快”执行指定的函数。具体而言,函数的执行会放置在事件队列的下一个计时器开始。但是请注意,这不是立即执行:函数不会被执行除非下一个计时器开始。这就是为什么在上述的例子中,调用 console.log(4) 发生在调用 console.log(3) 之前(因为调用 console.log(3) 是通过setTimeout被调用的,因此会稍微延迟)。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Karen110 Karen110
4年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Wesley13 Wesley13
3年前
Java爬虫之JSoup使用教程
title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin
可莉 可莉
3年前
11个棘手的JavaScript面试题
英文| https://medium.com/javascriptinplainenglish/doyouknowjavascript1f2b44461333翻译|web前端开发(ID:web\_qdkf)在本文中,将分享11个Javascript技巧面试问。这些题看起来很简单,但对答案却要三思而后行,因为它很容易做错。1
Stella981 Stella981
3年前
25 个最基本的 JavaScript 面试问题及答案(上)
1.使用typeofbar"object"来确定bar是否是对象的潜在陷阱是什么?如何避免这个陷阱?尽管typeofbar"object"是检查bar是否对象的可靠方法,令人惊讶的是在JavaScript中null也被认为是对象!因此,令大多数开发人员惊讶的是,下面的代码将输出true(而不是f
Wesley13 Wesley13
3年前
Unity5.6.4f1 配置WebGL教程
Unity5.6.4f1发布WebGL的配置教程步骤一:先查看自带的Unity是否yi配置好WebGL的项,若无,则可遵循以下教程来设置!(https://oscimg.oschina.net/oscnet/54612ae3d9b094f1db96b00b1c81a5fe432.png)步骤二:下图是我已经设置好的,未设置
Wesley13 Wesley13
3年前
Java面向对象技术
问题及答案来源自《Java程序员面试笔试宝典》第四章Java基础知识4.2面向对象技术1、面向对象与面向过程有什么区别?看下面一个实例即可:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候依次调用;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而
Stella981 Stella981
3年前
53道java多线程面试题整理及答案(2018年)
最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案。为此我业余时间整理了Java多线程相关的53道常见面试题,及详细答案,你可以用它来好好准备面试。望各路大牛,发现不对的地方,不吝赐教,留言即可。1)什么是线程?线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
代码揽虹客
代码揽虹客
Lv1
找一方净土,守一份剩下流年,看一段岁月安好。
文章
7
粉丝
0
获赞
0