8.你如何比较 Object 和 Map
Object 与Maps 的相似之处在于,它们都允许您将键设置为值、检索这些值、删除键以及检测某个键是否存储了某些内容。由于这个原因,对象在历史上被用作地图。但是在某些情况下,使用 Map 有一些重要的区别。
Object 的键是字符串和符号,而它们可以是 Map 的任何值,包括functions、Object 和任何primitive。
Map 中的键是有序的,而添加到 Object 的键不是。因此,当迭代它时,一个 Map 对象按插入的顺序返回键。
您可以使用 size 属性轻松获取 Map 的大小,而 Object 中的属性数量必须手动确定。
Map 是可迭代的,因此可以直接迭代,而迭代 Object 需要以某种方式获取其键并对其进行迭代。
一个对象有一个原型,所以如果你不小心,地图中有一些默认的键可能会与你的键发生冲突。从 ES5 开始,这可以通过使用 map =Object.create(null) 绕过,但很少这样做。
Map在涉及频繁添加和删除密钥对的场景中可能表现得更好。
9.== 和 === 运算符有什么区别?
JavaScript 提供了严格(===, !==) 和类型转换(==, !=) 相等比较。严格运算符考虑变量的类型,而非严格运算符根据变量的值进行类型校正/转换。严格的运算符遵循以下不同类型的条件,
当两个字符串具有相同的字符序列、相同的长度以及相应位置的相同字符时,它们是严格相等的。
当两个数字在数值上相等时,它们严格相等。即,具有相同的数值。这里有两种特殊情况,
NaN 不等于任何东西,包括 NaN。
正零和负零彼此相等。
如果两个布尔操作数都为真或都为假,则两个布尔操作数严格相等。
如果两个对象引用同一个对象,则它们严格相等。
Null 和 Undefined 类型与 === 不相等,但与 == 相等。即, null===undefined --> false 但 null==undefined --> true
一些涵盖上述情况的例子,
0 == false // true 0 === false // false 1 == "1" // true 1 === "1" // false null == undefined // true null === undefined // false '0' == false // true '0' === false // false []==[] or []===[] //false, refer different objects in memory {}=={} or {}==={} //false, refer different objects in memory
10.什么是 lambda 或 箭头函数?
箭头函数是函数表达式的较短语法,没有自己的this、arguments、super 或 new.target。这些函数最适合非方法函数,它们不能用作构造函数。
11.什么是头等函数?
在 Javascript 中,函数是第一类对象。头等函数意味着该语言中的函数被视为任何其他变量。
例如,在这种语言中,一个函数可以作为参数传递给其他函数,可以由另一个函数返回,也可以作为一个值分配给一个变量。例如,在下面的示例中,分配给侦听器的处理函数
const handler = () => console.log ('This is a click handler function');
document.addEventListener ('click', handler);
12.什么是一阶函数?
一阶函数是不接受另一个函数作为参数并且不返回函数作为其返回值的函数。
const firstOrder = () => console.log ('I am a first order function!');
13.什么是高阶函数?
高阶函数是接受另一个函数作为参数或返回一个函数作为返回值或两者兼而有之的函数。
const firstOrderFunc = () => console.log ('Hello, I am a First order function'); const higherOrder = ReturnFirstOrderFunc => ReturnFirstOrderFunc(); higherOrder(firstOrderFunc);
14.什么是一元函数?
一元函数(即 monadic)是一个只接受一个参数的函数。它代表一个函数接受的单个参数。
让我们以一元函数为例,
const unaryFunction = a => console.log (a + 10); // 给给定的参数加 10
15.什么是柯里化函数?
柯里化是将具有多个参数的函数转换为每个只有一个参数的函数序列的过程。Currying 以数学家Haskell Curry 的名字命名。通过应用柯里化,n 元函数将其变成一元函数。
让我们举一个 n-ary 函数的例子,以及它如何变成一个柯里化函数,
const multiArgFunction = (a, b, c) => a + b + c; console.log(multiArgFunction(1,2,3));// 6 const curryUnaryFunction = a => b => c => a + b + c; curryUnaryFunction (1); // return a function: b => c => 1 + b + c curryUnaryFunction (1) (2); // return a function: c => 3 + c curryUnaryFunction (1) (2) (3); // return 数字 6
16.什么是纯函数?
一个纯函数是在返回值是由它的参数没有任何副作用只有确定的函数。即如果您在应用程序中调用具有相同参数 ‘n’ 次和 ‘n’ 个位置的函数,则它将始终返回相同的值。
我们举个例子来看看纯函数和非纯函数的区别,
//不纯 let numberArray = []; const impureAddNumber = number => numberArray.push(number); //纯 const pureAddNumber = number => argNumberArray => argNumberArray.concat([number]); //显示结果 console.log (impureAddNumber(6)); // returns 1 console.log (numberArray); // returns [6] console.log (pureAddNumber(7) (numberArray)); // returns [6, 7] console.log (numberArray); // returns [6]
根据上面的代码片段,通过改变数组并返回一个与参数值无关的推送数字索引,推送函数本身是不纯的。而另一方面,Concat获取数组并将其与另一个数组连接起来,产生一个没有副作用的全新数组。此外,返回值是前一个数组的串联。
请记住,纯函数很重要,因为它们简化了单元测试,没有任何副作用,也不需要依赖注入。它们还避免了紧密耦合,并通过没有任何副作用使您的应用程序更难中断。这些原则通过优先使用const 而不是let与 ES6 的不变性概念结合在一起。
17.let 关键字的用途是什么?
let语句声明了一个块作用域局部变量。因此,使用 let 关键字定义的变量的范围仅限于使用它的块、语句或表达式。而使用var关键字声明的变量用于定义全局变量或局部变量,而不管块作用域如何。
我们举个例子来演示一下用法,
let counter = 30;
if (counter === 30) {
let counter = 31;
console.log(counter); // 31
}
console.log(counter); // 30 (因为这里不存在 if 块中的变量)
18.let 和 var 有什么区别?
以表格格式列出差异
var let
它从 JavaScript 开始就可用 作为 ES6 的一部分引入
它有函数作用域 它有块作用域
变量将被提升 已提升但未初始化
让我们举个例子看看区别,
function userDetails(username) { if(username) { console.log(salary); // 由于变量提升未定义 console.log(age); // 参考错误:初始化前无法访问"age" let age = 30; var salary = 10000; } console.log(salary); //10000 (可访问到适当的函数范围) console.log(age); //error:age未定义(由于块作用域) } userDetails('Haiyong');
19. 为什么选择 let 这个名字作为关键字?
let是一种数学语句,被早期的编程语言如Scheme和Basic 所采用。它是从数十种其他语言中借用而来的,这些语言let已经尽可能地作为传统关键字使用var。
20.你如何在没有错误的情况下重新声明 switch 块中的变量?
如果您尝试在 a 中重新声明变量,switch block则会导致错误,因为只有一个块。例如,下面的代码块抛出如下语法错误,
let counter = 1; switch(x) { case 0: let name; break; case 1: let name; // 重新声明的语法错误。 break; }
为避免此错误,您可以在 case 子句中创建一个嵌套块并创建一个新的块范围词法环境。
let counter = 1; switch(x) { case 0: { let name; break; } case 1: { let name; // 没有用于重新声明的 SyntaxError。 break; } }