你应该知道的25道Javascript面试题

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?

(function(){

var a = b = 3;

})();

console.log("a defined? " + (typeof a !== ‘undefined’));

console.log("b defined? " + (typeof b !== ‘undefined’));

这题不难,IIFE 中的赋值过程其实是(赋值过程从右到左):

(function(){

b = 3;

var a = b;

})();

接下去就不难了,a 是局部变量,b 是全局变量。

=


What will the code below output to the console and why?

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?

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’ 的缩写,表示 “不是一个数字”,通常会在运算过程中产生:

console.log(‘abc’ / 4);

console.log(4 * ‘a’);

虽然它 “不是一个数字”,但是 NaN 的 typeof 结果却是 number:

console.log(typeof (4 * ‘a’)); // number

NaN 和任何变量都不相等,包括 NaN 自己:

console.log(NaN === NaN); // false

判断一个变量是不是 NaN 可以用 isNaN() 函数,但是这 并不是一个完美的函数,有些时候用 value !== value 似乎更准确,幸运的是,ES6 已经有 Number.isNaN() 方法,将比 isNaN() 准确的多。

=


What will the code below output? Explain your answer.

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 中没有自带的方法,可以把一个数去掉小数点后和原数进行比较,判断是否相等,那么问题就演变成如何对一个数进行取整了。

var a = -1.2223;

console.log(a ^ 0); // -1

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?

(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.

判断一个字符串是不是回文。

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.

console.log(sum(2,3)); // Outputs 5

console.log(sum(2)(3)); // Outputs 5

写一个 sum 方法,使得以上代码得到预期结果。这题可以参考我以前的文章 汤姆大叔的6道javascript编程题题解 中的最后一题,理论上此题更简单,因为它没要求能扩展(比如 sum(2)(3)(4)),甚至可以这样:

function sum(x) {

if (arguments.length == 2) {

return arguments[0] + arguments[1];

} else {

return function(y) { return x + y; };

}

}

或者这样:

function sum(x, y) {

if (y !== undefined) {

return x + y;

} else {

return function(y) { return x + y; };

}

}

十三

==


Consider the following code snippet:

for (var i = 0; i < 5; i++) {

var btn = document.createElement(‘button’);

btn.appendChild(document.createTextNode('Button ’ + i));

btn.addEventListener(‘click’, function(){ console.log(i); });

document.body.appendChild(btn);

}

(a) What gets logged to the console when the user clicks on “Button 4” and why?

(b) Provide one or more alternate implementations that will work as expected.

点击 ‘Button 4’ 后输出什么?如何使得输出能跟预期相同?

答案是输出 5,事实上点击任意的 button,输出都是 5。因为循环结束后,i 值变成了 5。如何改,使得输出分别是 0, 1, 2, 3, 4?用闭包在内存中保存变量,可以参考我之前的文章 这10道javascript笔试题你都会么 中的第 8 题。

十四

==


What will the code below output to the console and why?

var arr1 = “john”.split(‘’);

var arr2 = arr1.reverse();

var arr3 = “jones”.split(‘’);

arr2.push(arr3);

console.log(“array 1: length=” + arr1.length + " last=" + arr1.slice(-1));

console.log(“array 2: length=” + arr2.length + " last=" + arr2.slice(-1));

上面代码输出是?

这道题我答错了,忽略了 reverse() 方法的一个要重性质,reverse() 方法执行的结果并不是创建一个副本,而是在原数组上直接操作,并返回该数组的引用。

知道了这一点,该题也就迎刃而解了。arr2 其实和 arr1 引用了同一个对象,所以在 arr2 上的操作也会同时反映到 arr1 上。

十五

==


What will the code below output to the console and why ?

console.log(1 + “2” + “2”);

console.log(1 + +“2” + “2”);

console.log(1 + -“1” + “2”);

console.log(+“1” + “1” + “2”);

console.log( “A” - “B” + “2”);

console.log( “A” - “B” + 2);

以上代码输出什么?

+“2” 能将字符串 “2” 转换成整数 2,-“2” 同理,而两个变量进行 “+” 运算时,如果都是数字和字符串,则分别进行数字相加和字符串拼接,如果一个是数字一个是字符串,则将数字转为字符串,如果是 “-” 运算呢?则将字符串转为数字。

“A” - “B” 会返回 NaN,因为 “A” 和 “B” 无法转成数字进行运算,这里不要以为 “A” 和 “B” 能转为 ASCII码 进行运算(不要和 C 语言搞混了)。而 NaN 和字符串相加,会转成 “NaN” 和字符串去拼接,NaN 和任何数字相加结果还是 NaN。

十六

==


The following recursive code will cause a stack overflow if the array list is too large. How can you fix this and still retain the recursive pattern?

var list = readHugeList();

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item…

nextListItem();

}

};

以上代码可能会由于递归调用导致栈溢出,如何规避这个问题?

首先,任何递归都可以用迭代来代替,所以改写成迭代方式肯定没有问题。

而原文给的解答令人深思:

var list = readHugeList();

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item…

setTimeout( nextListItem, 0);

}

};

利用 setTimeout 的异步性质,完美地去除了这个调用栈。

如果你还是摸不着头脑,简单举个栗子:

var list = [0, 1];

var nextListItem = function() {

var item = list.pop();

if (item) {

nextListItem();

}

console.log(item);

};

nextListItem();

上面的代码会依次输出 0 和 1,因为程序中形成了一个调用栈,1 被压到了栈底,最后出栈。

把程序改成这样:

var list = [0, 1];

var nextListItem = function() {

var item = list.pop();

if (item) {

// process the list item…

setTimeout( nextListItem, 0);

}

console.log(item);

};

nextListItem();

这回就是 1 和 0 了,因为 setTimeout 的回调只有当主体的 js 执行完后才会去执行,所以先输出了 1,自然也就没有栈这一说法了。

事实上,并不是所有递归都能这样改写,如果下一次递归调用依赖于前一次递归调用返回的值,就不能这么改了。

十七

==


What is a “closure” in JavaScript? Provide an example.

谈谈闭包。

以前也写过几篇文章,可以参考下 闭包初窥 以及 闭包拾遗 & 垃圾回收机制

十八

==


What will be the output of the following code:

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
了。

十七

==


What is a “closure” in JavaScript? Provide an example.

谈谈闭包。

以前也写过几篇文章,可以参考下 闭包初窥 以及 闭包拾遗 & 垃圾回收机制

十八

==


What will be the output of the following code:

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-VG6s59Rf-1715824482694)]

[外链图片转存中…(img-rWGaQpxY-1715824482694)]

[外链图片转存中…(img-GR0rjBPF-1715824482695)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值