几个常见题目
下面这段代码,浏览器控制台上会打印什么?
var a = 10
function foo() {
console.log(a)
var a = 20
}
foo()
2
3
4
5
6
答案: undefind
解析: 执行 foo 函数的时候 a 导致了变量提升,但是变量提升只提升声明,不提升赋值,所以 a 为 undefind
我们使用 let 或 const 代替 var,输出是否相同
var a = 10
function foo() {
console.log(a)
var a = 20
}
foo()
2
3
4
5
6
答案: 在浏览器 console 种使用 let 替换导致了报错
解析: let 定义的变量必须要先申明
"newArray"中有哪些元素?
var array = []
for (var i = 0; i < 3; i++) {
array.push(() => i)
}
var newArray = array.map(el => el())
console.log(newArray)
2
3
4
5
6
答案: [3,3,3]
解析: 首先要明确 array 中存放的是返回 i 的匿名函数即 () => i
。在 for 循环中,array 的每一项保存了该匿名函数,其中的 i 为 i 这个值的引用。
foo
函数,是否会导致堆栈错误?
运行function foo() {
setTimeout(foo, 0)
}
2
3
答案: 不会
解析: foo
函数的执行会导致死循环,但并不会造成堆栈错误。因为setTimeout
是伪异步执行,当你将函数交由setTimeout
处理后,原来的函数并不会等待,会继续执行,函数可以结束,资源也就可以释放。
foo
函数,页面是否会有响应
运行function foo() {
return Promise.resolve().then(foo)
}
2
3
答案: 页面直接卡爆,慎重测试!
解析: 本质上Promise
是 es6 中为了异步操作解决地域回调问题来设计出的语法糖。简而言之,Promise
是 基于 callback 实现的,在Promise
resolve 以后,依然需要执行 callback 方法,此时内存不会释放。
我们能否以某种方式为下面的语句使用展开运算而不导致类型错误
var obj = {x:1,y:2,z:3}
[...obj];//TypeError
// 实际上对象的展开运算符在ES7中才添加
2
3
展开语法 和 for-of 语句遍历 iterable 对象定义要遍历的数据。Array 或 Map 是具有默认迭代行为的内置迭代器。对象不是可迭代的,但是可以通过使用 iterable 和 iterator 协议使它们可迭代。
在Mozilla文档中,如果一个对象实现了@@iterator
方法,那么它就是可迭代的,这意味着这个对象(或者它原型链上的一个对象)必须有一个带有@@iterator
键的属性,这个键可以通过常量Symbol.iterator
获得。
示例如下
var obj = { x: 1, y: 2, z: 3 }
obj[Symbol.iterator] = function() {
// iterator 是一个具有 next 方法的对象,
// 它的返回至少有一个对象
// 两个属性:value&done。
// 返回一个 iterator 对象
return {
next: function() {
if (this._countDown === 3) {
const lastValue = this._countDown
return { value: this._countDown, done: true }
}
this._countDown = this._countDown + 1
return { value: this._countDown, done: false }
},
_countDown: 0
}
}
;[...obj] // 打印 [1, 2, 3]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
还可以使用generator
函数来定制对象的迭代行为:
var obj = {x:1, y:2, z: 3}
obj[Symbol.iterator] = function*() {
yield 1;
yield 2;
yield 3;
}
[...obj]; // 打印 [1, 2, 3]
2
3
4
5
6
7
8
运行以下代码片段时,控制台上会打印什么?
var obj = { a: 1, b: 2 }
Object.setPrototypeOf(obj, { c: 3 })
Object.defineProperty(obj, 'd', { value: 4, enumerable: false })
// what properties will be printed when we run the for-in loop?
for (let prop in obj) {
console.log(prop)
}
2
3
4
5
6
7
8
答案: a,b,c
解析: for-in 循环遍历对象本身的可枚举属性以及对象从其原型继承的属性。 可枚举属性是可以在 for-in 循环期间包含和访问的属性。enmuerable
xGetter()
会打印什么值?
var x = 10
var foo = {
x: 90,
getX: function() {
return this.x
}
}
foo.getX() // prints 90
var xGetter = foo.getX
xGetter() // prints ??
2
3
4
5
6
7
8
9
10
答案: 10
解析: xGetter()
中的this
指向了window