100道JavaScript 面试题和答案(下)
英文 | https://betterprogramming.pub/100-javascript-interview-questions-58e22e30f7f1
翻译 | 杨小二
let p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'the first promise');
});
let p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'the second promise');
});
Promise.race([p1, p2]).then(function(value) {
console.log(value, 'was faster');
});
the second promise was faster
52、 promise.all() 方法有什么作用?
Promise.all 是一个将一系列承诺作为输入的承诺。它在以下情况下得到解决:
要么所有的输入承诺都得到解决。
或者他们中的任何一个被拒绝。
例如, promise.all 等待所有这三个 promise 完成:
var prom1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Yay!");
}, 1000);
});
var prom2 = Promise.resolve(10);
var prom3 = 100;
Promise.all([prom1, prom2, prom3]).then(values => {
console.log(values);
});
["Yay", 10, 100]
53、 eval() 函数是什么?
eval() 函数计算字符串中的代码。要计算的字符串可以是表达式、变量、语句或语句序列。
例如:
console.log(eval("5+10"));
15
54、什么是事件冒泡?
在事件冒泡中,事件通过最里面的元素运行事件处理程序开始。然后它触发父母的事件处理程序,直到它到达最外面的元素。
看到这一点的最佳方法是创建一个在 div 中包含 div 的 HTML 文档:
<style>
body * {
margin: 20px;
border: 1px solid blue;
}
</style>
<div onclick="alert('Outer layer')">Outer layer
<div onclick="alert('Middle layer')">Middle layer
<div onclick="alert('Inner layer')">Inner layer
</div>
</div>
</div>
在每个 div 中,都有一个 JavaScript 警报,当单击该 div 时会触发该警报。
结果页面如下所示:
如果你现在单击内层,它会触发分配给该 div 的警报,并触发父 div 的警报。
55、 什么是时间死区?
时间死区意味着变量不可达,即使它已经在范围内。
让我们首先看看,当你尝试将未初始化的变量记录到控制台时会发生什么:
console.log(x);
var x = "Yay";
undefined
你可能希望这会导致错误,但它会打印 undefined。
发生这种情况是因为所有声明都被移到了作用域的顶部。由于提升,上面的代码在引擎盖下的行为如下:
var x;
console.log(x);
x = "Yay";
这里 undefined 被自动分配给顶部的变量。这使得在定义它之前使用它成为可能。
但是让我们看看当我们使用 let 而不是 var 做同样的事情时会发生什么:
console.log(x);
let x = 10;
error: Uncaught ReferenceError: Cannot access 'x' before initialization
发生这种情况是因为 let 的提升方式与 var 不同。当一个 let 变量被提升时,它不会变成未定义的。相反,它是无法访问的,或者在被分配值之前处于时间死区。
56、什么是URI?
URI 或统一资源标识符是一组区分资源的字符。URI 允许互联网协议在资源之间执行操作。
URI 可能如下所示:
hello://example.com:8042/there?name=jack#sumthing
57、什么是DOM?
当网页加载完毕后,浏览器会为该页面创建一个 DOM。这使 JavaScript 能够创建动态 HTML。
DOM 或文档对象模型充当 HTML 文档的 API。它定义了文档的结构。它还指定如何访问和修改文档。
58、文档加载还是 DOMContentLoaded?
DOMContentLoaded 事件在 HTML 文档被加载和解析后被触发。它不会等待资产(例如样式表和图像)。
文档加载事件仅在整个页面加载后触发,包括所有资产。
例如,以下是如何使用 DOMContentLoaded 在 DOM 已完全加载时发出通知:
window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM is now loaded!');
});
window.addEventListener('load', (event) => {
console.log('The page is now loaded!');
});
59、HTML 属性 vs DOM 属性?
当你编写 HTML 时,你可以在 HTML 元素上定义属性。然后,当你使用浏览器打开页面时,你的 HTML 代码将被解析。
至此,一个DOM节点就创建好了。这个 DOM 节点对应于你刚刚编写的 HTML 文档。这个 DOM 节点是一个具有属性的对象。
例如,这个 HTML 元素:
<input id="my-input" type="text" value="Name:">
具有三个属性,id、type 和 value。
当浏览器解析这个 HTML 元素时。
它接受这个输入字段并从中烘焙一个 HTMLInputElement 对象。
这个对象有几十个属性,比如accept、accesKey、align。
它还将一些原始 HTML 属性转换为属性,例如 id 和类型。但是例如, value 属性不引用 value 属性。
60、什么是同源政策?
同源策略是一种有价值的安全机制。它可以防止 JavaScript 跨越域边界发出请求。
源是指 URI 方案、主机名和端口号。同源策略使得一个页面上的脚本无法访问另一页面上的敏感数据。
61、JavaScript 是编译型语言还是解释型语言?
JavaScript 是一种解释型语言。
浏览器中的解释器读取 JavaScript 代码,解释每一行,然后运行它。
62、JavaScript 是区分大小写的语言吗?
JavaScript 是一种区分大小写的语言。
关键字、变量、函数名等需要大写一致。
为了演示,这段代码有效
let i = 1;
while(i < 2) {
console.log(i);
i++;
}
let i = 1;
WHILE(i < 2) {
console.log(i);
i++;
}
63、JavaScript 有多少个线程?
JavaScript 使用单个线程。它不允许编写解释器可以在多个线程或进程中并行运行的代码。
这意味着它按顺序执行代码,并且必须先执行完一段代码,然后才能转到下一段代码。
看到这一点的一个很好的例子是当你在网页上显示警报时。警报弹出后,在警报关闭之前,你无法与页面交互。
alert("Hello there!");
64、 “break”语句有什么作用?
break 语句跳出循环并继续执行循环外的代码。
例如,此循环在遇到数字 5 后终止:
for (var i = 0; i < 100; i++) {
if (i === 5) {
break;
}
console.log('Number is ', i);
}
console.log('Yay');
Number is 0
Number is 1
Number is 2
Number is 3
Number is 4
Yay
65、 “continue”语句的作用是什么?
continue 语句跳过一轮循环。
例如,这个循环跳过数字 2 和 3:
for (var i = 0; i < 5; i++) {
if (i === 2 || i === 3) {
continue;
}
console.log('Number is ', i);
}
0
1
4
66、什么是正则表达式?
正则表达式,也称为 regex 或 regexp,是形成搜索模式的一组字符。它是一种常用于 JavaScript 和其他编程语言的模式匹配工具。
例如,让我们使用正则表达式从字符串中查找任何数字:
var regex = /\d+/g;
var string = "You have 100 seconds time to run";
var matches = string.match(regex);
console.log(matches);
[100]
例如,正则表达式可用于在大型文本文件中搜索电子邮件或电话号码。
67、调试代码时断点的目的是什么?
断点允许你查找 JavaScript 代码中的错误。
当执行调试器语句并出现调试器窗口时,你可以在代码中设置断点。
在断点处,JavaScript 停止执行并让你检查值和范围以解决可能的问题。
68、什么是条件运算符?
条件运算符是编写 if-else 语句的简写。条件运算符有时称为三元运算符。
例如:
// Regular if-else expression:
const age = 10;
if(age < 18){
console.log("Minor");
} else {
console.log("Adult");
}
// Conditional operator shorthand for the above if-else
age < 18 ? console.log("Minor") : console.log("Adult");
69、你能链接条件运算符吗?
对的,这是可能的。有时它很有用,因为它可以使代码更易于理解。
让我们看一个例子:
function example() {
if (condition1) { return value1; }
else if (condition2) { return value2; }
else if (condition3) { return value3; }
else { return value4; }
}
// Shorthand for the above function
function example() {
return condition1 ? value1
: condition2 ? value2
: condition3 ? value3
: value4;
}
70、 freeze() 方法有什么作用?
freeze() 方法冻结一个对象。它使对象不可变。
冻结对象后,无法向其添加新属性。
例如:
const item = { name: "test" };
Object.freeze(item);
item.name = "Something else"; // Error
71、如何获取对象的键列表?
使用 Object.keys() 方法。
例如:
const student = {
name: 'Mike',
gender: 'male',
age: 23
};
console.log(Object.keys(student));
["name", "gender", "age"]
72、JavaScript 的原始数据类型是什么?
原始数据类型具有原始值。JavaScript 中有七种不同的原始数据类型:
string——单词。例如“约翰”。
number — 数值。例如12。
boolean — 真或假。例如真。
null — 没有值。例如让 x = null;
undefined — 声明变量但没有值的类型。例如,当以这种方式创建变量 x 时,让 x; , x 变为未定义。
bigint — 表示大于 2^53-1 的整数的对象。例如 BigInt(121031393454720292)
symbol — 用于创建独特符号的内置对象。例如 let sym1 = Symbol(‘test’)
73、有哪些方法可以访问对象的属性?
共有三种访问属性的方法。
点符号。
例如:
obj.property
方括号表示法。
例如:
obj["property"]
表达式符号。
例如:
obj[expression]
74、页面加载后如何执行JavaScript代码?
你可以通过三种方式执行此操作:
将属性 window.onload 设置为在页面加载后执行的函数:
window.onload = function ...
document.onload = function ...
<body onload="script();">
75、什么是错误对象?
错误对象是一个内置对象,如果发生错误,它会为你提供详细的错误信息。
错误对象有两个属性:
name
message
例如,假设 sayHi() 函数抛出错误。发生这种情况时,catch 块会为你提供一个错误对象,例如,你可以将其打印到控制台。
try {
sayHi("Welcome");
}
catch(error) {
console.log(error.name + "\n" + error.message);
}
76、NoScript 标签有什么作用?
Noscript 标签用于检测和响应禁用 JavaScript 的浏览器。
你可以使用 noscript 标签来执行一段通知用户的代码。
例如,你的 HTML 页面可以有一个像这样的 noscript 标签:
<script>
document.write("Hello World!");
</script>
<noscript>
Your browser does not support JavaScript!
</noscript>
77、 什么是入口控制循环?
在入口控制循环中,条件在进入循环体之前进行测试。
例如,for 循环和 while 循环就属于这一类:
let nums = [1,2,3];
for (let num of nums) {
console.log(num);
}
1
2
3
78、什么是出口控制循环?
在退出控制循环中,在循环结束时评估条件。这意味着无论条件为真还是假,循环体至少执行一次。
例如,do-while 循环就属于这一类:
const i = 0;
do {
console.log('The number is', i);
} while (i !== 0);
The number is 0
79、什么是匿名函数?
匿名函数是没有名字的函数。
匿名函数通常分配给变量名称或用作回调函数。
这是一个带有名称供参考的函数:
function example(params) {
// do something
}
const myFunction = function() {
// do something
};
[1, 2, 3].map(function(element) {
// do something
});
80、什么是迭代器?
迭代器协议使对象生成一系列值成为可能。
迭代器必须实现 next() 方法来获取序列中的下一个值。此方法返回一个对象
value - 迭代序列中的下一个值
done - 如果此值是序列中的最后一个,则为真。如果不是,那就是假的。
这是创建和使用迭代器的示例。这个函数实现了一个可以被 rangeIter(1,5) 调用的范围迭代器,并打印值 1 2 3 4。
// define a function that returns an iterator
function rangeIter(start = 0, end = Infinity, step = 1) {
let nextIndex = start;
let count = 0;
// create the actual iterator object
const iterator = {
// create the next() method that knows how to get the next value in the sequence
next: function() {
let result;
if (nextIndex < end) {
// Return the value and set done 'false' because the iteration is not completed
result = { value: nextIndex, done: false }
nextIndex += step;
count++;
return result;
}
// set done 'true' when the end has been reached
return { value: count, done: true }
}
};
// return an iterator object
return iterator;
}
// Using the iterator
const it = rangeIter(1, 5);
let result = it.next();
while (!result.done) { // prints 1 2 3 4
console.log(result.value);
result = it.next();
}
81、什么是可迭代对象?
可迭代协议意味着一个对象可以被迭代,因此实现了迭代器协议(问题 80。)
换句话说,你可以在任何可迭代对象上使用 for...of 循环来循环遍历它生成的值序列。
例如,Array 或 Map 在 JavaScript 中是可迭代的,但 Object 不是。
下面是一个在数组上应用 for...of 循环的例子,它本质上是可迭代的:
const nums = [1,2,3];
for (let num of nums) {
console.log(num);
}
1
2
3
82、 什么是生成器?
生成器是迭代器的替代品。你可以编写具有非连续执行的迭代代码。换句话说,可以暂停生成器函数的执行。
生成器是使用 function* 语法定义的。它们不是返回值,而是产生值。
创建时,生成器不执行其代码。相反,它们返回一个 Generator 对象,它本质上是一个迭代器。当你对生成器对象调用 next() 时,它会运行代码直到遇到 yield 语句,然后停止。
例如,这是一个与上面迭代器部分中的迭代器完全相同的生成器:
// Create a generator function that returns an iterator
function* rangeIter(start = 0, end = Infinity, step = 1) {
let count = 0;
for (let i = start; i < end; i += step) {
count++;
yield i;
}
return count;
}
// Create a generator object
const it = rangeIter(1, 5);
// Use the generator exactly how you'd use an iterator
let result = it.next();
while (!result.done) { // prints 1 2 3 4
console.log(result.value);
result = it.next();
}
rangeIter 函数比迭代器示例中的 rangeIter 更容易阅读。然而,两者都做完全相同的事情。
83、什么是 for of 循环?
For...of 循环可用于在 JavaScript 中迭代可迭代对象。
例如,你可以使用 for...of 循环打印数组的内容:
const nums = [1,2,3];
for (const num of nums) {
console.log(num);
}
1
2
3
84、什么是nodejs?
Node.js 建立在 Chrome 的 JS 运行时之上。它是一个以可扩展方式构建网络应用程序的平台。
85、什么是事件循环?
事件循环是一个回调函数队列。它处理所有异步回调。
当异步函数执行时,回调函数被推入队列。JavaScript 引擎不会在异步任务完成之前触发事件循环。
例如,事件循环的结构可能如下所示:
while (queue.waitForMessage()) {
queue.processNextMessage();
}
86、什么是一元运算符?
一元 运算符+用于将变量转换为数字。
如果变量无法转换,则转换为 NaN(这是数字的特殊情况,因此类型仍然是数字)。
例如:
let str = "10";
let num = +str;
console.log(typeof str, typeof num);
let word = "Hello";
let n = +word;
console.log(typeof word, typeof n, n);
string, number
string, number, NaN
87、如何对数组的元素进行排序?
使用 sort() 对数组的项进行排序。这不会创建新数组,而是“就地”对原始数组进行排序,即直接修改它。
let months = ["Adam", "Sam", "Jack", "Bill"];
months.sort();
console.log(months);
["Adam", "Bill", "Jack", "Sam"]
88、什么是TypeScript ?
TypeScript 是带有类型的 JavaScript。它是由 Microsoft 创建的 JavaScript 超集。
TypeScript 在普通 JavaScript 中添加了诸如可选类型、类、async/await 等类型。
这是 TypeScript 函数的一个简单示例:
function greet(name: string): string {
return "Hello, " + name;
}
console.log(greet("Michael"));
89、 JavaScript 中的构造函数是什么?
构造函数是用于创建和初始化类对象的方法。当你从一个类中实例化一个新对象时,它就会被执行。
例如:
class Student {
constructor() {
this.name = "Mike";
}
}
let student = new Student();
console.log(student.name);
Mike
90、什么是ES6?
ES6 (ECMAScript 6) 是 JavaScript 编程语言的第六个版本。它于2015年6月发布。
91、什么是模板字面量?
模板文字允许你直接在字符串中嵌入表达式。
使用模板文字时,不要用引号声明字符串,而是使用反引号 (`)。
要将变量或表达式嵌入到字符串中,需要在 ${} 之间添加
例如:
console.log(`This is the ${10 * 10}th time`)
This is the 100th time
92、如何在没有第三个变量的情况下交换两个变量?
使用解构从数组中提取值。这也可用于在没有第三个帮助程序的情况下交换两个变量:
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b)
2 1
93、什么是 ArrayBuffer?
ArrayBuffer 是通用且固定长度的二进制数据缓冲区。
let buffer = new ArrayBuffer(16);
console.log(buffer.byteLength)
16
Math 对象从 Math 原型继承属性
数组对象从数组原型继承属性。
原型是对象的特征。它描述了与之相关的属性。它充当对象的蓝图。
function Fruit(name, weight) {
this.name = name;
this.weight = weight;
}
Fruit.prototype.description = "Yum!";
// Traditional function
var sum = function(a,b){
return a + b;
}
// Arrow Function
var sum = (a,b) => a + b;
const student = { "name":"Mike", "id": 132123, "city": "New York"};
console.dir(student);
<body oncontextmenu="return false;">
function greet(name){
console.log('Hello', name);
}
function circleArea(radius) {
return Math.PI * Math.pow(radius, 2);
}
const PersonDetails = {
name: "Matty",
age: 42,
married: false
}
const name = PersonDetails.name;
const age = PersonDetails.age;
const married = PersonDetails.married;
console.log(name);
console.log(age);
console.log(married);
但是从 ES6 开始,你可以通过使用对象解构用一行代码来做到这一点:
const PersonDetails = {
name: "Matty",
age: 42,
married: false
}
const {name, age, married} = PersonDetails;
console.log(name);
console.log(age);
console.log(married);
结论
谢谢阅读。我希望你喜欢它。
祝你面试或考试好运。
编程快乐!
PS:到这里,这100道面试题就已经全部分享完毕了,希望对你有所帮助,同时也欢迎你在留言区跟我留言,告诉我,你还想学习那些方面的知识。
学习更多技能
请点击下方公众号