本文原文来自 Medium ,本文仅进行翻译,如需转载请注明来源!
作为一门灵活的编程语言,JS中有很多缺陷,这很可能被人们所忽略,而产生很大的失误,在本文中,我们将通过10个容易出错的示例来学习JS语法的一些关键部分,有些甚至是现实世界中的错误,而某些示例则直接来自于JS的基本语法。
看以下代码,回答问题:
const { var1: a, var2, var3 = 10 } = { var1: 2, var2: NaN, var3: 5 };
function testFn(){
let sum = 0;
for(const ele of arguments){
if(ele !== ele) break;
else sum += ele;
}
return sum;
}
const res = testFn(a,var2,var3);
console.log(res);
该代码的输出是什么?
(1) 12 (2) NaN (3) 2 (4) 7
argument
变量中检索输入参数(可以将代码改为箭头函数,看看会发生什么)看以下代码,回答问题:
function testFn(){
const a = {} && -1 || 0;
console.log(a / 0);
}
testFn();
该代码将会输出什么?
(1) false (2) Error (3) NaN (4)-Infinity
&&
或是||
返回最后检查的值,而不是简单的布尔值''
,null
,NaN
,-0
,0
,+0
,false
都是Falsy值-Infinity
或Infinity
代替抛出错误看以下代码,回答问题:
function testFn(){
const a = "3.14";
const b = -a - + - + 3.14;
const c = a + + - + 3.14;
console.log(b + c);
}
testFn();
该代码将会输出什么?(1) 3.14 (2) "03.14-3.14" (3) NaN (4)-3.14
+
,-
可用于字符串到数字的强制转换+
运算符和数字之间使用的运算符会将数字强制为字符串值###示例4 Promise 流控制
看以下代码,回答问题:
function testFn(){
const p = new Promise((rsv,rjt) => {
console.log("1");
rsv();
}).then(res => {
console.log("2");
setTimeout(() => {
console.log("3");
}, 0);
});
console.log("4");
setTimeout(() => {
console.log("5");
}, 0);
console.log("6");
}
testFn();
该代码将会输出什么?
(1) > "1" > "4" > "6" > "2" > "5" > "3"
(2) > "4" > "6" > "1" > "5" > "2" > "3"
(3) > "1" > "4" > "6" > "2" > "3" > "5"
(4) > "1" > "4" > "6" > "5" > "2" > "3"
看以下代码,回答问题:
function testFn(fn){
try{
fn();
}catch(err) {
console.log("Error caught: ", err.message);
}
}
function innerFn(){
throw Error("Error from Synchronous Fn");
}
async function innerAsyncFn(){
throw Error('Error from Asynchronous Fn');
}
testFn(innerFn);
testFn(innerAsyncFn);
以下哪个是输出的内容?
(1) Error caught: Error from Synchronous Fn Error caught: Error from Asynchronous Fn
(2) Error caught: Error from Synchronous Fn Uncaught (in promise) Error: Error from Asynchronous Fn
(3) Uncaught Error: Error from Synchronous Fn Uncaught (in promise) Error: Error from Asynchronous Fn
(4) Uncaught Error: Error from Synchronous Fn Error caught: Error from Asynchronous Fn
return new Promise.reject(Error('msg'))
被拒绝的Promise将在Promise.catch()中进行处理.Uncaught Error
,如果try{}catch(e){}
在当前函数范围内未被处理,则将引发该错误到函数调用的外部范围看以下代码,回答问题:
async function testFn(){
console.log('start');
const sampleArr = [1, 2, 3];
for(const ele of sampleArr){
const val = await ele;
console.log(val);
}
console.log('end');
}
testFn();
以下哪个是输出的值?
(1)
'start'
1
2
3
'end'
(2)
'start'
'end'
1
2
3
如果使用以下做法呢?
async function testFn(){
console.log('start');
const sampleArr = [1, 2, 3];
sampleArr.forEach(async ele => {
const val = await ele;
console.log(val);
});
console.log('end');
}
testFn();
async
和await
可以成对使用(尽管async
可以是多个await
),这意味着await关键字将仅使其对应async函数的执行同步。如果将异步函数作为参数传递给第三方函数处理程序,那么该第三方函数处理程序在当前作用域中将变为黑色,并且将会失去对异步函数的控制。async
箭头函数传递给.forEach()
函数,因此await
仅在异步箭头函数的作用域内起作用。但是在第一段代码中,for循环没有作用域范围,这意味着 await可以和该函数的作用域一起使用。var obj1 = {
name: "John Wick",
gender: "male",
myFn: function(val){
var innerFn = function(val2){
console.log(val, val2, this.name);
}.bind(this);
return innerFn;
}
};
var obj2 = {
name: "Trinity",
gender: "female"
};
obj2.testFn = obj1.myFn;
obj2.testFn("Hello")("World");
看看以下哪个是输出结果
(1) undefined "World" "John Wick" (2) "Hello" "World" "John Wick" (3) undefined "World" "Trinity" (4) "Hello" "World" "Trinity"
this
关键字始终指向引用当前函数的对象val
内部变量innerFn
引用外部作用域的变量val
。此引用是从一个作用域范围到外部范围的引用。.bind(this)
强制绑定innerFn
到其外部范围的调用函数const object1 = {a: 1, b: 2, c: 3};
const object2 = Object.create(object1,{
d: {
value: 4,
enumerable: true
}
});
object2.e = 5;
const newObj = {
...object2
};
console.log("new obj: ", newObj);
//Array spreading
const array1 = ['a', 'b', 'c'];
const array2 = Object.create(array1,{
3: {
value: 'd',
enumerable: true
}
});
const newArr = [...array2];
console.log("new arr:", newArr);
以下哪个是输出的结果?
(1)
new obj: {d: 4, e: 5}
new arr: ["a", "b", "c"]
(2)
new obj: {a: 1, b: 2, c: 3, d: 4, e: 5}
new arr: ["a", "b", "c", "d"]
(3)
new obj: {a: 1, b: 2, c: 3, d: 4, e: 5}
new arr: ["a", "b", "c"]
(4)
new obj: {d: 4, e: 5}
new arr: ["a", "b", "c", "d"]
...
扩展操作符在对象上使用仅迭代对象自身的属性,类似于for (const prop in Object.keys(obj))
。另一方面,for ( const prop in obj)
将仅迭代原型链中的所有属性。...
在数组上使用时将遍历数组对象的原型链中的所有可迭代的元素,类似于for (const ele of arr)
{
const valArr = [null || 0, {}, null];
function testFn(val) {
switch (typeof val){
case "object":
console.log("object");
break;
case "number":
console.log("number");
break;
case "null":
console.log("null");
break;
default:
break;
}
};
valArr.forEach(testFn);
}
以下哪个是输出的结果?
(1) "number" "object" "null" (2) "null" "object" "object" (3) "number" "object" "object" (4) "null" "object" "null"
null
在JS中也是一个对象||
操作返回最后的检查值0
即使0
是一个falsy值
const obj1 = {
name: "John Wick",
gender: "male"
};
const obj2 = Object.assign({}, obj1);
const obj3 = obj1;
const obj4 = {
...obj1
};
console.log(obj1 === obj2);
console.log(obj1 === obj3);
console.log(obj1 === obj4);
以下哪个是输出的内容?
(1) true true false (2) false true true (3) false false false (4) false true false
=
用于对象分配的是分配对象引用(浅拷贝),而不是将对象真正复制到新对象(深拷贝)。要使用深拷贝,就要用Object.assign()
或...
运算符===
逻辑运算符在对象上使用时将检查两个对象是否都引用相同的对象内存。希望看完了本文之后,能够学习到一些新的内容,当然,在本文中有许多知识并不需要讲(例如深拷贝,Promise等等),这些内容大家可以在很多地方看到。