嗨喽码农们:
又见面了,继上次分享的面试题,今天再为大家分享一些关于js 那些面试常见的问题。希望对大家有帮助,喜欢的可以点赞收藏起来。
五、小心javascript自动插入分号机制
在《JavaScript语言精粹》这本书里,这个“自动插入分号”机制被划入到了JavaScript的毒瘤里面,与之并列的前面的全局变量。
有些时候,不合时宜地插入分号,会导致严重的后果。 比如一个return语句要正确返回一个值,这个值的表达式的开始部分必须和return位于同一行。
今天,我们就来聊聊这个知识点,看下面的代码函数,它们会返回什么?
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,也没有任何错误抛出。
原因是这样的,当碰到 foo2()中包含return语句的代码行(代码行上没有其他任何代码),分号会立即自动插入到返回语句之后。请仔细留意上面两个函数中return的不同之处,foo2函数的return是单独一行的。
也不会抛出错误,因为代码的其余部分是完全有效的,即使它没有得到调用或做任何事情(相当于它就是是一个未使用的代码块,定义了等同于字符串 "hello"的属性 bar)。
所以,在使用return语句的时候,要留意javascript的这个特点,尽可能不要将return关键字写在独立的一行,避免不必造成不必要的错误。
六、NaN 是什么?如何测试一个值是否等于 NaN ?
NaN 这个知识点的问题在《趣味ES6》的系列很多人留言说觉得很绕,不好理解,的确,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。因为只有NaN 这货,才会自己不等于自己。
另外,ES6提供了一个新的 Number.isNaN() 函数,这是一个不同的函数,并且比老的全局 isNaN() 函数更可靠。
七、下面的代码运行结果是什么?
例子1:
console.log(1 + "2" + "2");
得到的结果是:“122”;
解析: 1 + “2” + “2” 输出: “122” 。 1 + “2” 是执行的第一个操作。由于其中一个运算对象 “2” 是字符串,JavaScript会假设它需要执行字符串连接,因此,会将 1 的类转换为 “1” , 1+“2” 结果就是 “12” 。然后, “12”+“2” 就是 “122” 。
例子2:
console.log(1 + +"2" + "2");
得到的结果是:“32”;
解析: 1 + +“2” + “2” 输出: “32” 说明:根据运算的顺序,要执行的第一个运算是 +“2” (第一个 “2” 前面的额外 + 被视为一元运算符)。
因此,JavaScript将 “2” 的类型转换为数字,然后应用一元 + 号(即将其视为一个正数)。其结果就是得到一个数字 2 ,接下来的运算就是 1 + 2 ,这当然是 3 。
然后我们需要在一个数字和一个字符串之间进行运算(即, 3 和 “2”),同样的,JavaScript会将数值类型转换为字符串,并执行字符串的连接,产生 “32” 。
例子3:
console.log(1 + -"1" + "2");
得到的结果是:“02”;
解析: 1 + -“1” + “2” 输出: “02” 。这里的解释和前一个例子相同,不同的地方是此处的一元运算符是 - 而不是 + 。
先是 “1” 变为 1 ,然后当应用 - 时又变为了 -1 ,然后将其与 1 相加,结果为 0 ,再将其转换为字符串,连接最后的 “2” 运算对象,得到 “02” 。
例子4:
console.log(+"1" + "1" + "2");
得到的结果是:“112”;
解析: +“1” + “1” + “2” 输出: “112” 。虽然第一个运算对象 “1” 因为前缀的一元 + 运算符类型转换为数值,但当连接到第二个运算对象 “1” 的时候,又立即转换回字符串,然后又和最后的运算对象 “2” 连接,产生了字符串 “112” 。
例子5:
console.log( "A" - "B" + "2");
得到的结果是:“NaN2”;
解析: “A” - “B” + “2” 输出: “NaN2” 。由于运算符 - 不能被应用于字符串,并且 “A” 和 “B” 都不能转换成数值,因此, “A” - “B” 的结果是 NaN ,然后再和字符串 “2” 连接,得到 “NaN2” 。
例子6:
console.log( "A" - "B" + 2);
得到的结果是:NaN;
解析: “A” - “B” + 2 输出: NaN 。参见前一个例子, “A” - “B” 结果为 NaN 。但是,应用任何运算符到 NaN 与其他任何的数字运算对象,结果仍然是 NaN 。
八、关于逻辑运算符,下面代码运行的结果是什么?
逻辑运算符用于测定变量或值之间的逻辑。在我们实际开发过程中十分常用,所以面试官会把逻辑运算符的知识点当作考察应聘者的内容之一。
在JavaScript中, || 和 && 都是逻辑运算符,用于在从左至右计算时,返回第一个可完全确定的“逻辑值”。
讲解
或 || 运算符。在 X||Y 的表达式中,首先计算 X 并将其解释执行为一个布尔值。
如果这个布尔值true,那么返回true(1),不再计算 Y ,因为“或”的条件已经满足。
如果这个布尔值为false,那么我们仍然不能知道 X||Y 是真是假,直到我们计算 Y ,并且也把它解释执行为一个布尔值。
因此, 0||1 的计算结果为true(1),同理计算 1||2 。
与 && 运算符。在 X&&Y 的表达式中,首先计算 X 并将其解释执行为一个布尔值。
如果这个布尔值为 false,那么返回 false(0),不再计算 Y ,因为“与”的条件已经失败。
如果这个布尔值为true,但是,我们仍然不知道 X&&Y 是真是假,直到我们去计算 Y ,并且也把它解释执行为一个布尔值。 .
不过,关于 && 运算符有趣的地方在于,当一个表达式计算为“true”的时候,那么就返回表达式本身。
这很好,虽然它在逻辑表达式方面计算为“真”,但如果你希望的话也可用于返回该值。这就解释了为什么,有些令人奇怪的是, 1 && 2返回 2,而不是你以为的可能返回 true 或 1。
看完了讲解,大家可以试一下解答这个例子。
题目:
console.log( 0 || 1 );
console.log( 1 || 2 );
console.log( 0 && 1 );
console.log( 1 && 2 );
他们运行的结果是什么,在底下留言写下你的答案!
九、以下代码将输出什么?并解释你的答案。
看下面的代码,输出的结果是什么?并解释你的答案。
var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);
不少人可能会以为答案是 123 ,但结果是 456 ,为什么会是这样子的呢。
原因是我们忽略了一个知识点:JavaScript在设置对象的属性的时候,会暗中字符串化参数值。
在这里例子中,由于 b 和 c都是对象,把它们设置为对象a的参数,它们都将被转换为 “[object Object]” 。
结果就是, a[b] 和 a[c] 都相当 “[object Object]” ,而后者会将前者的值覆盖。
因此,设置或引用 a[c] 和设置或引用 a[b] 完全相同。所以得到的答案是 456 。
十、关于this指向,以下代码将输出什么?
var person = {
_name: ‘I am John’,
sayHello: function (){
return this._name;
}
};
var sayHello = person.sayHello;
console.log(sayHello());
console.log(person.sayHello());
var person = {
_name: 'I am John',
sayHello: function (){
return this._name;
}
};
var sayHello = person.sayHello;
console.log(sayHello());
console.log(person.sayHello());
代码运行的结果是:
undefined
I am John
第二个打印 person.sayHello() 的结果是: I am John 这个好理解。
为什么第一次打印出来的结果是 undefined 呢?明明是直接赋值过去的呀。这里涉及到的知识点就是:this的指向。
在执行 sayHello() 的时候,当访问到 this._name 时,此时的this已经不再是 person 对象,而是全局窗口对象,也就是 widnow 对象。
与此同时, widnow 对象并不存在 _name 属性,所以返回的是 undefined 。
所以在笔试面试看到一些代码题目的时候,如果你看到了 this ,就要小心谨慎,很可能这里就是面试官要考(keng)察(ni)的地方。
今天分享到此,下次继续!