常常写业务就容易忽视对基础知识的补充和增强,但在面试中,基础知识点是很是重要的考核部分。本文要分享的是,一位开发者天天都会发布的 JavaScript 问题。有的容易,有的会有难度,对基础知识的查缺补漏很是有帮助,也是你进阶路上必然要掌握的知识。javascript
如下挑选了10个问题,紧跟其后的就是对这道题的详细解答。若是你想看全部的题目,最后有连接直达。前端
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) } for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) }
0 1 2
和 0 1 2
0 1 2
和 3 3 3
3 3 3
和 0 1 2
答案: Cjava
因为 JavaScript 的事件循环,setTimeout
回调会在遍历结束后才执行。由于在第一个遍历中遍历 i
是经过 var
关键字声明的,因此这个值是全局做用域下的。在遍历过程当中,咱们经过一元操做符 ++
来每次递增 i
的值。当 setTimeout
回调执行的时候,i
的值等于 3。git
在第二个遍历中,遍历 i
是经过 let
关键字声明的:经过 let
和 const
关键字声明的变量是拥有块级做用域(指的是任何在 {} 中的内容)。在每次的遍历过程当中,i
都有一个新值,而且每一个值都在循环内的做用域中。github
function getPersonInfo(one, two, three) { console.log(one) console.log(two) console.log(three) } const person = 'Lydia' const age = 21 getPersonInfo`${person} is ${age} years old`
"Lydia"
21
["", " is ", " years old"]
["", " is ", " years old"]
"Lydia"
21
"Lydia"
["", " is ", " years old"]
21
答案: B面试
若是使用标记模板字面量,第一个参数的值老是包含字符串的数组。其他的参数获取的是传递的表达式的值!数组
function sayHi() { return (() => 0)() } typeof sayHi()
"object"
"number"
"function"
"undefined"
答案: B函数
sayHi
方法返回的是当即执行函数(IIFE)的返回值.此当即执行函数的返回值是 0
, 类型是 number
ui
参考:只有7种内置类型:null
,undefined
,boolean
,number
,string
,object
和 symbol
。 function
不是一种类型,函数是对象,它的类型是object
。this
const a = {} const b = { key: 'b' } const c = { key: 'c' } a[b] = 123 a[c] = 456 console.log(a[b])
123
456
undefined
ReferenceError
答案: B
对象的键被自动转换为字符串。咱们试图将一个对象 b
设置为对象 a
的键,且相应的值为 123
。
然而,当字符串化一个对象时,它会变成 "[object Object]"
。所以这里说的是,a["[object Object]"] = 123
。而后,咱们再一次作了一样的事情,c
是另一个对象,这里也有隐式字符串化,因而,a["[object Object]"] = 456
。
而后,咱们打印 a[b]
,也就是 a["[object Object]"]
。以前刚设置为 456
,所以返回的是 456
。
const person = { name: 'Lydia' } function sayHi(age) { console.log(`${this.name} is ${age}`) } sayHi.call(person, 21) sayHi.bind(person, 21)
undefined is 21
Lydia is 21
function
function
Lydia is 21
Lydia is 21
Lydia is 21
function
答案: D
使用这两种方法,咱们均可以传递咱们但愿 this
关键字引用的对象。可是,.call
是当即执行的。
.bind
返回函数的副本,但带有绑定上下文!它不是当即执行的。
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
1
2
and 3
3
and 6
4
1
2
and 2
3
and 3
4
1
undefined
and 2
undefined
and 3
undefined
and 4
undefined
1
2
and undefined
3
and undefined
4
答案: D
reducer
函数接收4个参数:
reducer
函数的返回值将会分配给累计器,该返回值在数组的每一个迭代中被记住,并最后成为最终的单个结果值。
reducer
函数还有一个可选参数initialValue
, 该参数将做为第一次调用回调函数时的第一个参数的值。若是没有提供initialValue
,则将使用数组中的第一个元素。
在上述例子,reduce
方法接收的第一个参数(Accumulator)是x
, 第二个参数(Current Value)是y
。
在第一次调用时,累加器x
为1
,当前值“y”
为2
,打印出累加器和当前值:1
和2
。
例子中咱们的回调函数没有返回任何值,只是打印累加器的值和当前值。若是函数没有返回值,则默认返回undefined
。 在下一次调用时,累加器为undefined
,当前值为“3”, 所以undefined
和3
被打印出。
在第四次调用时,回调函数依然没有返回值。 累加器再次为 undefined
,当前值为“4”。 undefined
和4
被打印出。
const firstPromise = new Promise((res, rej) => { setTimeout(res, 500, "one"); }); const secondPromise = new Promise((res, rej) => { setTimeout(res, 100, "two"); }); Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
"one"
"two"
"two" "one"
"one" "two"
答案: B
当咱们向Promise.race
方法中传入多个Promise
时,会进行 优先 解析(注:只要有一个成功或失败,就立马结束)。在这个例子中,咱们用setTimeout
给firstPromise
和secondPromise
分别设定了500ms和100ms的定时器。这意味着secondPromise
会首先解析出字符串two
。那么此时res
参数即为two
,是为输出结果。
function greeting() { throw "Hello world!"; } function sayHi() { try { const data = greeting(); console.log("It worked!", data); } catch (e) { console.log("Oh no an error!", e); } } sayHi();
"It worked! Hello world!"
"Oh no an error: undefined
SyntaxError: can only throw Error objects
"Oh no an error: Hello world!
答案: D
经过throw
语句,我么能够建立自定义错误。 而经过它,咱们能够抛出异常。异常能够是一个字符串, 一个 数字, 一个 布尔类型 或者是一个 对象。在本例中,咱们的异常是字符串'Hello world'
.
经过 catch
语句,咱们能够设定当try
语句块中抛出异常后应该作什么处理。在本例中抛出的异常是字符串'Hello world'
. e
就是这个字符串,所以被输出。最终结果就是'Oh an error: Hello world'
.
// index.js console.log('running index.js'); import { sum } from './sum.js'; console.log(sum(1, 2)); // sum.js console.log('running sum.js'); export const sum = (a, b) => a + b;
running index.js
, running sum.js
, 3
running sum.js
, running index.js
, 3
running sum.js
, 3
, running index.js
running index.js
, undefined
, running sum.js
答案: B
import
命令是编译阶段执行的,在代码运行以前。所以这意味着被导入的模块会先运行,而导入模块的文件会后执行。
这是CommonJS中require()
和import
之间的区别。使用require()
,您能够在运行代码时根据须要加载依赖项。 若是咱们使用require
而不是import
,running index.js
,running sum.js
,3
会被依次打印。
const settings = { username: "lydiahallie", level: 19, health: 90 }; const data = JSON.stringify(settings, ["level", "health"]); console.log(data);
"{"level":19, "health":90}"
"{"username": "lydiahallie"}"
"["level", "health"]"
"{"username": "lydiahallie", "level":19, "health":90}"
答案: A
JSON.stringify
的第二个参数是 _替代者(replacer)_. 替代者(replacer)能够是个函数或数组,用以控制哪些值如何被转换为字符串。
若是替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为"level"
和 "health"
的属性被包括进来, "username"
则被排除在外。 data
就等于 "{"level":19, "health":90}"
.
而若是替代者(replacer)是个 _函数_,这个函数将被对象的每一个属性都调用一遍。
函数返回的值会成为这个属性的值,最终体如今转化后的JSON字符串中(译者注:Chrome下,通过实验,若是全部属性均返回同一个值的时候有异常,会直接将返回值做为结果输出而不会输出JSON字符串),而若是返回值为undefined
,则该属性会被排除在外。
题目来源:https://github.com/lydiahallie/javascript-questions/blob/master/README-zh_CN.md
若是对你有帮助,请关注【前端技能解锁】: