题目来自 25 Essential JavaScript Interview Questions。闲来无事,正好切一下。
一
What is a potential pitfall with using typeof bar === "object"
to determine if bar is an object? How can this pitfall be avoided?
老生常谈的问题,用 typeof
是否能准确判断一个对象变量,答案是否定的,null
的结果也是 object,Array
的结果也是 object,有时候我们需要的是 “纯粹” 的 object 对象。
如何规避这个问题?
1 2 3 4 5 6 7 |
var obj = {}; // 1 console.log((obj !== null) & (typeof obj === "object") && (toString.call(obj) !== "[object Array]")); // 2 console.log(Object.prototype.toString.call(obj) === "[object Object]"); |
二
What will the code below output to the console and why?
1 2 3 4 5 6 |
(function(){ var a = b = 3; })(); console.log("a defined? " + (typeof a !== 'undefined')); console.log("b defined? " + (typeof b !== 'undefined')); |
这题不难,IIFE 中的赋值过程其实是(赋值过程从右到左):
1 2 3 4 |
(function(){ b = 3; var a = b; })(); |
接下去就不难了,a 是局部变量,b 是全局变量。
三
What will the code below output to the console and why?
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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(); |
前面两个输出没有问题,都是 bar,问题出在后面两个。用了 IIFE 后,匿名函数内的 this 其实已经指到了 window,所以第三个输出 this.foo 其实是 window.foo,而全局对象并没有 foo 这个 key,所以输出 undefined,而第四个输出,因为 self 引用了 myObject,所以还是 bar。
四
What is the significance of, and reason for, wrapping the entire content of a JavaScript source file in a function block?
为什么要用 IIFE?
简单来说就是为了能模块化,创建私有变量等等,很多类库(比如 jQuery)都用了这样的写法。
可以参考我以前翻译的一篇文章 详解javascript立即执行函数表达式(IIFE)
五
What is the significance, and what are the benefits, of including ‘use strict’ at the beginning of a JavaScript source file?
严格模式下进行 Javascript 开发有啥好处?
这个就不展开来了,可以参考阮一峰老师的 Javascript 严格模式详解 或者自行谷歌百度。
六
Consider the two functions below. Will they both return the same thing? Why or why not?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function foo1() { return { bar: "hello" }; } function foo2() { return { bar: "hello" }; } |
执行以上两个函数,会返回相同的东西吗?
不会,第二个函数会返回 undefined
。这是由于 Javascript 的封号插入机制决定的,如果某行代码,return 关键词后没有任何东西了,将会自动插入一个封号,显然 foo2 函数中,当 return 后被插入一个封号后,尽管后面的语句不符合规定,但是因为没有执行到,所以也不会报错了。没有 return 任何东西的函数,默认返回 undefined。
所以很多 Javascript 规范建议把 { 写在一行中,而不是另起一行。
七
What is NaN? What is its type? How can you reliably test if a value is equal to NaN?
NaN 是什么鬼?typeof 的结果是?如果一个变量的值是 NaN,怎么确定?
NaN 是 ‘not a number’ 的缩写,表示 “不是一个数字”,通常会在运算过程中产生:
1 2 |
console.log('abc' / 4); console.log(4 * 'a'); |
虽然它 “不是一个数字”,但是 NaN 的 typeof 结果却是 number:
1 |
console.log(typeof (4 * 'a')); // number |
NaN 和任何变量都不相等,包括 NaN 自己:
1 |
console.log(NaN === NaN); // false |
判断一个变量是不是 NaN 可以用 isNaN()
函数,但是这 并不是一个完美的函数,有些时候用 value !== value
似乎更准确,幸运的是,ES6 已经有 Number.isNaN()
方法,将比 isNaN()
准确的多。
八
What will the code below output? Explain your answer.
1 2 |
console.log(0.1 + 0.2); console.log(0.1 + 0.2 == 0.3); |
上面代码的输出结果是什么?
这个问题正好我之前研究过,有兴趣的可以参考下 【0.1 + 0.2 = 0.30000000000000004】该怎样理解?,看懂了还有兴趣的可以看下这篇 玉伯的一道课后题题解(关于 IEEE 754 双精度浮点型精度损失)
九
Discuss possible ways to write a function isInteger(x)
that determines if x
is an integer.
写一个方法 isInterger(x),可以用来判断一个变量是否是整数。
ES6 中自带了 Number.isInteger()
方法。但是目前 ES5 中没有自带的方法,可以把一个数去掉小数点后和原数进行比较,判断是否相等,那么问题就演变成如何对一个数进行取整了。
1 2 3 4 5 6 7 8 |
var a = -1.2223; console.log(a ^ 0); // -1 console.log(a | 0); // -1 console.log(a > 0); // -1 console.log(Math.round(a)); // -1 console.log(Math.floor(a)); // -2 console.log(Math.ceil(a)); // -1 |
十
In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
1 2 3 4 5 6 |
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })(); |
以上代码的输出结果是?
这题不难,只要知道 Javascript 是单线程的语言, 一些异步事件是在主体 js 执行完之后执行即可,所以主体的 1、4 先输出,而后是 3、2,没有问题,因为 3 的定时设置比 2 早。
具体可以参考我之前的文章 从setTimeout谈JavaScript运行机制
十一
Write a simple function (less than 80 characters) that returns a boolean indicating whether or not a string is a palindrome.
判断一个字符串是不是回文。
1 2 3 4 |
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); } |
这里想到一个进阶题,求字符串最长回文子串,可以参考 求最长回文子串 – leetcode 5. Longest Palindromic Substring
十二
Write a sum
method which will work properly when invoked using either syntax below.