400个最常见的 JavaScript 面试问答(42)
写在前面的
点击 订阅专栏,即可查阅全部内容及后续更新
大家好,我是 海拥 ,专注于前端知识的分享。今天将给大家带来的是 400 个最常见的 JavaScript 面试问答第 42 部分,也是最后一部分。
大家一定要记得点赞收藏呀,关注我的牛客账号 海拥 ,并且三连(点赞+收藏+评论)本篇文章,可以找我要一本计算机相关的书。
411.什么是正确的尾调用?
首先,在谈论“正确的尾调用”之前,我们应该先了解尾调用。尾调用是作为调用函数的最终动作执行的子例程或函数调用。而适当的尾调用 (PTC)是一种技术,当函数调用是尾调用时,程序或代码不会为递归创建额外的堆栈帧。
例如,下面的经典或阶乘函数的头递归依赖于每个步骤的堆栈。每一步都需要处理到n * factorial(n - 1)
function factorial(n) {
if (n === 0) {
return 1
}
return n * factorial(n - 1)
}
console.log(factorial(5)); //120
但是,如果您使用尾递归函数,它们会在不依赖堆栈的情况下继续将所需的所有数据传递到递归中。
function factorial(n, acc = 1) {
if (n === 0) {
return acc
}
return factorial(n - 1, n * acc)
}
console.log(factorial(5)); //120
上述模式返回与第一个相同的输出。但是累加器将 total 作为参数进行跟踪,而无需在递归调用中使用堆栈内存。
412.如何检查一个对象是否是一个promise?
如果你不知道一个值是否是一个promise,包装该值作为Promise.resolve(value)它返回一个承诺
function isPromise(object){
if(Promise && Promise.resolve){
return Promise.resolve(object) == object;
}else{
throw "Promise not supported in your environment"
}
}
var i = 1;
var promise = new Promise(function(resolve,reject){
resolve()
});
console.log(isPromise(i)); // false
console.log(isPromise(p)); // true
另一种方法是检查.then()处理程序类型
function isPromise(value) {
return Boolean(value && typeof value.then === 'function');
}
var i = 1;
var promise = new Promise(function(resolve,reject){
resolve()
});
console.log(isPromise(i)) // false
console.log(isPromise(promise)); // true
413.如何检测函数是否被调用为构造函数?
您可以使用new.target伪属性来检测函数是作为构造函数(使用 new 运算符)还是作为常规函数调用调用的。
如果使用 new 运算符调用构造函数或函数,则 new.target 返回对构造函数或函数的引用。 对于函数调用,new.target 是未定义的。
function Myfunc() {
if (new.target) {
console.log('called with new');
} else {
console.log('not called with new');
}
}
new Myfunc(); // called with new
Myfunc(); // not called with new
Myfunc.call({}); not called with new
414.arguments 对象和rest 参数之间有什么区别?
arguments 对象和 rest 参数之间有三个主要区别
1.arguments 对象是一个类似数组的对象,但不是一个数组。而rest 参数是数组实例。 2.arguments 对象不支持 sort、map、forEach 或 pop 等方法。而这些方法可用于rest 参数。 3.rest 参数只是那些没有被赋予单独名称的参数,而参数对象包含传递给函数的所有参数
415.扩展运算符和rest 参数之间有什么区别?
Rest 参数将所有剩余元素收集到一个数组中。而Spread运算符允许将可迭代对象(数组/对象/字符串)扩展为单个参数/元素。即,Rest 参数与扩展运算符相反。
416.有哪些不同种类的 generators(生成器)?
有五种生成器,
1.生成器函数声明:
function* myGenFunc() {
yield 1;
yield 2;
yield 3;
}
const genObj = myGenFunc();
2.生成器函数表达式:
const myGenFunc = function* () {
yield 1;
yield 2;
yield 3;
};
const genObj = myGenFunc();
3.对象字面量中的生成器方法定义:
const myObj = {
* myGeneratorMethod() {
yield 1;
yield 2;
yield 3;
}
};
const genObj = myObj.myGeneratorMethod();
4.class 中的生成器方法定义:
class MyClass {
* myGeneratorMethod() {
yield 1;
yield 2;
yield 3;
}
}
const myObject = new MyClass();
const genObj = myObject.myGeneratorMethod();
5.生成器作为计算属性:
const SomeObj = {
*[Symbol.iterator] () {
yield 1;
yield 2;
yield 3;
}
}
console.log(Array.from(SomeObj)); // [ 1, 2, 3 ]
417.什么是内置可迭代对象?
下面是 javascript 中内置的可迭代对象列表,
1.数组和类型数组
2.字符串:迭代每个字符或 Unicode 代码点
3.Maps:迭代其键值对
4.集合:迭代它们的元素
5.参数:函数中类似数组的特殊变量
6.NodeList 等 DOM 集合
418.for…of 和 for…in 语句之间有什么区别?
for...in 和 for...of 语句都遍历 js 数据结构。唯一的区别在于它们迭代的内容:
for..in 迭代对象的所有可枚举属性键 for..of 迭代可迭代对象的值。 让我们用一个例子来解释这种差异,
let arr = ['a', 'b', 'c'];
arr.newProp = 'newVlue';
// key 是属性键
for (let key in arr) {
console.log(key);
}
// value 是属性值
for (let value of arr) {
console.log(value);
}
由于 for..in 循环遍历对象的键,第一个循环在遍历数组对象时记录 0、1、2 和 newProp。for..of 循环遍历 arr 数据结构的值并在控制台中记录 a、b、c。
419.如何定义实例和非实例属性?
Instance 属性必须在类方法中定义。例如,名称和年龄属性定义的内部构造函数如下,
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
但是必须在 ClassBody 声明之外定义 Static(class) 和原型数据属性。让我们为 Person 类分配年龄值,如下所示,
Person.staticAge = 30;
Person.prototype.prototypeAge = 40;
420.isNaN 和 Number.isNaN 有什么区别?
1.isNaN:全局函数isNaN将参数转换为数字,如果结果值为 NaN,则返回 true。 2.Number.isNaN:此方法不转换参数。但当类型为 Number 且值为 NaN 时,它返回 true。 让我们通过一个例子来看看区别,
isNaN(‘hello’); // true
Number.isNaN('hello'); // false
421.如何在没有任何额外括号的情况下调用 IIFE?
立即调用函数表达式(IIFE)需要一对括号来包装包含语句集的函数。
(function(dt) {
console.log(dt.toLocaleTimeString());
})(new Date());
由于 IIFE 和 void 运算符都会丢弃表达式的结果,因此您可以避免使用void operatorfor IIFE的额外括号,如下所示,
void function(dt) {
console.log(dt.toLocaleTimeString());
}(new Date());
422.可以在 switch case 中使用表达式吗?
您可能已经看到在 switch 条件中使用的表达式,但也可以通过为 switch 条件分配真值来用于 switch case。让我们以基于温度的天气状况为例,
const weather = function getWeather(temp) {
switch(true) {
case temp < 0: return 'freezing';
case temp < 10: return 'cold';
case temp < 24: return 'cool';
default: return 'unknown';
}
}(10);
423.忽略promise 错误的最简单方法是什么?
忽略promise 错误的最简单和最安全的方法是使该错误无效。这种方法也是 ESLint 友好的。
await promise.catch(e => void e);
424.如何使用 CSS 设置控制台输出的样式?
您可以使用 CSS 格式内容说明符 %c 将 CSS 样式添加到控制台输出。控制台字符串消息可以附加在另一个参数中的说明符和 CSS 样式之后。让我们使用 console.log 和 CSS 说明符打印红色文本,如下所示,
console.log("%cThis is a red text", "color:red");
还可以为内容添加更多样式。比如上面的文字可以修改font-size
console.log("%cThis is a red text with bigger font", "color:red; font-size
最后,不要忘了❤或📑支持一下哦,你的支持是海海更新的动力!关注我后面会持续分享面试经验 & 前端相关的专业知识。
🎁粉丝福利
1.关注我的牛客账号 海拥 ,并且三连(点赞+收藏+评论)本篇文章,可以找我要一本计算机相关的书。 2.老粉经常三连的话送两本或者多本书也不是不行。 送书信息收集表🐬:https://docs.qq.com/form/page/DRXl1VWJGU1ZvWmRv
最后祝大家都能找到满意的实习和 offer!
点击下方卡片进入详情页订阅专栏,即可查看完整内容~~
#JavaScript##面试题#在本专栏中,我们将讨论面试中经常被问到的 400 多个常见的 JavaScript 面试问题,包括各种原生 JavaScript 的难点,学成之后可以使用 JavaScript 做一些酷炫的小游戏、工具等。如果你是正在学习前端的学生,对前端感兴趣想学习 JavaScript,或者是想找前端相关的工作却从未接触过 JavaScript,一头雾水不知从何学起。你都可以订阅本专栏,这将是你的最佳入门读物