7个常见的 JavaScript 测验及解答[每日前端夜话0xDE]
介绍
我相信学习新事物并评估我们所知的东西对自己的进步非常有用,可以避免了我们觉得自己的知识过时的情况。在本文中,我将介绍一些常见的 JavaScript 知识。请享用!
1.声明
查看以下代码,并回答输出的内容(以及原因)。
1// situation 1 2console.log(person); 3var person = 'John'; 4 5// situation 2 6console.log(person); 7let person = 'Phill'; 8 9// situation 3 10console.log(person); 11const person = 'Frank'; 12 13// situation 4 14const person = 'Vanessa'; 15console.log(person); 16person = 'Mike'; 17console.log(person); 18 19// situation 5 20var person = 'John'; 21let person = 'Mike'; 22console.log(person); 23 24// situation 6 25var person = 'John'; 26if (person) { 27 let person = 'Mike'; 28 console.log(person); 29} 30console.log(person);
说明
Situation 1:预期结果是在控制台中看到文本 John
,但是令人惊讶的是,我们看到记录了 undefined
。想知道为什么吗?
好吧,这是经典的 JavaScript 在起作用。这种行为被称为 提升 。在后台,该语言将变量声明和值分配分为两部分。不管变量最初由开发人员在哪里声明,变量都将移动到顶部,声明时将其值设置为 undefined
。看起来像这样:
1var person; 2console.log(person); 3person = 'John';
Situation 2:在这里,结果将是引用错误。
1Uncaught ReferenceError: Cannot access 'person' before initialization
错误文本说明了一切。因为我们使用了关键字 let
,所以我们的变量被提升,但没有初始化,并且抛出该错误,通知我们正在尝试访问未初始化的变量。在 ES6 中引入了关键字 let
,使我们能够使用块作用域中的变量,从而帮助我们防止意外行为。
在这里,我们会得到与 Situation 2 中相同的错误。
不同之处在于我们使用了关键字 const
,从而防止在初始化后重新分配变量。ES6 中也引入了此关键字。
Situation 4:在这种情况下,我们可以看到关键字 const
是如何工作的,以及它如何避免无意中重新分配变量。在我们的示例中,首先会在控制台中看到 Vanessa
,然后是一个类型错误。
1Uncaught TypeError: Assignment to constant variable
const
变量的使用随着我们的代码库呈指数增长。
Situation 5:如果已经在某个作用域内使用关键字 var
定义了变量,则在同一作用域中用关键字 let
再次声明该变量将会引发错误。
因此,在我们的示例中,将不会输出任何内容,并且会看到语法错误提示。
1Uncaught SyntaxError: Identifier 'person' has already been declared
Situation 6:我们分别有一个函数作用域的变量,和块作用域的变量。在这种情况下,它们是否有相同的名字或标识符并不重要。
在控制台中,我们应该看到 Mike
和 John
被依次输出。为什么?
因为关键字 let
为我们提供了块作用域内的变量,这意味着它们仅存在于自己创建的作用域内,在这种情况下,位于 if...else
语句中。内部变量优先于外部变量,这就是为什么我们可以使用相同标识符的原因。
2.继承
考虑以下类,并尝试回答输出了什么以及为什么。
1class Person { 2 constructor() { 3 this.sayHello = () => { 4 return 'Hello'; 5 } 6 } 7 8 sayBye() { 9 return 'Bye'; 10 } 11} 12 13class Student extends Person { 14 sayHello() { 15 return 'Hello from Student'; 16 } 17} 18 19const student = new Student(); 20console.log(student.sayHello());
说明
如果你的答案是 Hello
,那是对的!
为什么:每次我们创建一个新的 Student
实例时,都会将 sayHello
属性设置为是一个函数,并返回字符串 Hello
。这是在父类( Person
)类的构造函数中发生的。
在 JavaScript 中,类是语法糖,在我们的例子中,在原型链上定义了 Student
类中的 sayHello
方法。考虑到每次我们创建 Student
类的实例时,都会将 sayHello
属性设置为该实例,使其成为返回字符串 Hello
的 function
,因此我们永远不会使用原型链上定义的函数,也就永远不会看到消息 Hello from Student
。
3.对象可变性
思考以下情况中每个部分的输出:
1// situation 1 2const user = { 3 name: 'John', 4 surname: 'Doe' 5} 6 7user = { 8 name: 'Mike' 9} 10 11console.log(user); 12 13// situation 2 14const user = { 15 name: 'John', 16 surname: 'Doe' 17} 18 19user.name = 'Mike'; 20console.log(user.name); 21 22// situation 3 23const user = { 24 name: 'John', 25 surname: 'Doe' 26} 27 28const anotherUser = user; 29anotherUser.name = 'Mike'; 30console.log(user.name); 31 32// situation 4 33const user = { 34 name: 'John', 35 surname: 'Doe', 36 address: { 37 street: 'My Street' 38 } 39} 40 41Object.freeze(user); 42 43user.name = 'Mike'; 44user.address.street = 'My Different Street'; 45console.log(user.name); 46console.log(user.address.street);
说明
Situation 1:正如我们在上一节中所了解的,我们试图重新分配不允许使用的 const
变量,所以将会得到类型错误。
控制台中的结果将显示以下文本:
1Uncaught TypeError: Assignment to constant variable
Situation 2:在这种情况下,即使我们改用关键字 const
声明的变量,也会有不同的行为。不同之处在于我们正在修改对象属性而不是其引用,这在 const
对象变量中是允许的。
控制台中的结果应为单词 Mike
。
Situation 3:通过将 user
分配给 anotherUser
变量,可以在它们之间共享引用或存储位置(如果你愿意)。换句话说,它们两个都会指向内存中的同一个对象,因所以更改一个对象的属性将反映另一个对象的更改。
控制台中的结果应为 Mike
。
Situation 4:在这里,我们使用 Object.freeze
方法来提供先前场景(Situation 3)所缺乏的功能。通过这个方法,我们可以“冻结”对象,从而不允许修改它的属性值。但是有一个问题!它只会进行浅冻结,这意味着它不会保护深层属性的更新。这就是为什么我们能够对 street
属性进行更改,而 name
属性保持不变的原因。
控制台中的输出依次为 John
和 My Different Street
。
4.箭头函数
运行以下代码段后,将会输出什么以及原因:
1const student = { 2 school: 'My School', 3 fullName: 'John Doe', 4 printName: () => { 5 console.log(this.fullName); 6 }, 7 printSchool: function () { 8 console.log(this.school); 9 } 10}; 11 12student.printName(); 13student.printSchool();
说明
控制台中的输出将依次为 undefined
和 My School
。
你可能会熟悉以下语法:
1var me = this; 2// or 3var self = this; 4 5// ... 6// ... 7// somewhere deep... 8// me.doSomething();
你可以把 me
或 self
变量视为父作用域,该作用域可用于在其中创建的每个嵌套函数。
当使用箭头函数时,这会自动完成,我们不再需要存储 this
引用来访问代码中更深的地方。箭头函数不绑定自己,而是从父作用域继承一个箭头函数,这就是为什么在调用 printName
函数后输出了 undefined
的原因。
5.解构
请查看下面的销毁信息,并回答将要输出的内容。给定的语法是否允许,否则会引发错误?
1const rawUser = { 2 name: 'John', 3 surname: 'Doe', 4 email: 'john@doe.com', 5 displayName: 'SuperCoolJohn', 6 joined: '2016-05-05', 7 image: 'path-to-the-image', 8 followers: 45 9} 10 11let user = {}, userDetails = {}; 12({ name: user.name, surname: user.surname, ...userDetails } = rawUser); 13 14console.log(user); 15console.log(userDetails);
说明
尽管有点开箱即用,但是上面的语法是允许的,并且不会引发错误!很整洁吧?
上面的语法功能强大,使我们能够轻松地将任何对象分成两个更具体的对象,上面的示例在控制台的输出为:
1// {name: "John", surname: "Doe"} 2// {email: "john@doe.com", displayName: "SuperCoolJohn", joined: "2016-05-05", image: "path-to-the-image", followers: 45}
6.异步/等待
调用以下函数后将输出什么?
1(async () => { 2 let result = 'Some Data'; 3 4 let promise = new Promise((resolve, reject) => { 5 setTimeout(() => resolve('Some data retrieved from the server'), 2000); 6 }); 7 8 result = await promise; 9 console.log(result); 10})();
说明
如果你认为是两秒钟后输出 Some data retrieved from the server
,那么你是对的!
代码将会暂停,直到 promise 得到解决。两秒钟后,它将继续执行并输出给定的文本。这意味着 JavaScript 引擎实际上会等到异步操作完成。可以说 async/await
是用来获得 promise 结果的语法糖。也有人认为它是比 promise.then
更具可读性的方式。
7. Return 语句
1const multiplyByTwo = (x) => { 2 return 3 { 4 result: x * 2 5 }; 6} 7console.log(multiplyByTwo(2));
说明
如果你的答案是 {result: 4}
,那你就错了。输出是 undefined
。但是不要对自己太苛刻,考虑到我也写 C# 代码,这也曾经困扰着我,这在 C# 那儿不是个问题。
由于自动分号插入【 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return#Automatic_Semicolon_Insertion 】的原因,上面的代码将返回 undefined
。 return 关键字和表达式之间不允许使用行结束符
解决方案是用以下列方式之一去修复这个函数:
1const multiplyByTwo = (x) => { 2 return { 3 result: x * 2 4 }; 5}
要么
1const multiplyByTwo = (x) => { 2 return ( 3 { 4 result: x * 2 5 } 6 ); 7}
原文: https://devinduct.com/blogpost/49/7-quick-javascript-pop-quizzes-with-explanations
下面夹杂一些私货:也许你和高薪之间只差这一张图
2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。
愿你有个好前程,愿你月薪30K。我们是认真的 !
在公众号内回复“体系”查看高清大图
长按二维码,加大鹏老师微信好友
拉你加入前端技术交流群
唠一唠怎样才能拿高薪
往期精选
小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。