一、简答题:
1、请说出下列最终的执行结果,并解释为什么?
var a = [];
for (var i = 0; i<10; i++) {
a[i] = function () {
console.log(i)
}
}
a[6]()
执行结果 10
执行结果分析:
这里涉及到了js语言的词法环境、变量存储、变量赋值、变量作用域链等相关内容的;从这个案例来看,运行环境开始形成上下文环境在这个运行环境中有两个变量,运行环境会开辟两个内存块;数组a和变量i,在这里的重点就是i的存储和赋值。i 通过自增操作,新的计算结果会覆盖上一次的结果,这这里i++ 运行的10次 所以i最终存储的数据是10;当调用 console.log(i) 时,会根据作用域链在当前环境中找i变变量所以取到的是10,这里还有一个要注意的就是 a[i] 作为下标的取值为什么每次都可以正确取到下标值呢?作为数组的赋值 a[i] 其实是一种语法糖, 其内部实现是函数的形式,此时的i是作为形参传入实现数组赋值的函数中。i 在实现数组的函数中又被建立了新的执行环境并在新的词法环境中被赋值调用;到这次数组赋值完成后。i的使命也就完成也就是i的变化 也不会再影响执行后的函数了。
2、请说出下列的执行结果,并解释为什么?
var tem = 123
if (true) {
console.log(tem)
let tem;
}
运行结果:报变量会在定义前使用的错误
执行结果分析:
这里涉及到了除了ES6 let 块级作用域的知识点;还有一个js变量声明和赋值的问题;js在执行中会先声明,后再执行的过程中再赋值;声明的过程就是一个开辟内存的过程;并在这个过程中执行检查变量重名、变量作用域范围的一些操作;在这个案例中 if 语句中是一个块级作用域,在执行之前首先,规定的该块级作用域中的变量 tem 并在遇到 tem = 100 时进行赋值;然而这里 console.log(tem) 执行在 let tem 之前所以就会报错;这里迷惑人判断的一点就是上层有个 var tem = 123 的赋值;因为上层的属于全局作用域,存在作用域链上的最顶端,如果块级作用存在同名的变量,就会阻断作用域链继续往上查找;
3、结合ES6新语法,用最简答的方法找出数组中的最小值;
var arr = [12, 34, 32, 89, 4]
答案:var min = arr.sort((pre, next) => pre - next)[0]
4、请详细说明 var、let、constant三种变量声明的方式之间的区别;
1、作用域的区别;2、是否能够变量提升
5、请说出下列的执行结果,并解释为什么?
var a = 10;
var obj = {
a: 20,
fn(){
setTimeout( () => {
console.log(this.a)
})
}
};
obj.fn(); // 20
var fn = obj.fn;
fn(); // 10
运行结果:20 10
执行结果分析:
this 关键字是 JS 很重要的一个部分,this指的是函数运行时所在的环境。obj.fn()是通过obj找到a,所以就是在obj环境执行。一旦var fn = obj.fn,变量fn就直接指向函数本身,所以fn()就变成在全局环境执行。
6、简述 Symbol类型的用途
(1)symbol 作为对象属性; (2)防止属性名称冲突; (3)模拟私有属性;
7、说说什么是浅拷贝什么是深拷贝;
产生深浅拷贝的的原因主要是因为JS存储机制产生的,对于数组、对象这种结构型数据类型,JS 这类类型的变量实际存储的是存贮这些数据的地址,所以执行复制操做的结果就是复制的这些数据的存储地址。这种操作称为浅复制;相反如果将该数据重新开辟一处内存将对应的数据拷贝到新的内存空间中去,这种操作成为深复制;
8、谈谈你是如何理解 JS 异步编程的,Even Loop 是做什么的,什么是宏任务什么是微任务?
异步编程是产生的背景是因为 JS 是一个单线程的执行语言;为了更好处理在单线程操作中出现阻塞的情况;JS 将一些耗时操作引入异步编程的方法来解决。 Event Loop 负责检查执行队列有没有待执行的任务; 微任务和宏任务都是异步操作; 微任务会先宏任务执行;
9、将下面异步代码使用 Promise 改进;
setTimeout(function(){
var a = 'hello';
setTimeout(function(){
var b = 'lagou';
setTimeout(function(){
var c = 'I love you';
console.log(a + b + c)
},10)
},10)
},10)
答案:
var say = function (msg) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(msg)
},10)
});
}
say('hello').then((msg) => {
return say(msg + ' ' + 'lagou')
}).then((msg) => {
return say(msg + ' ' + 'I love you')
}).then(msg => {
console.log(msg)
})
10、请简述 TypeScript 与 JavaScript 之间的关系;
TypeScript 是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以载入 JavaScript 代码运行,并扩展了 JavaScript 的语法。 TypeScript 具有以下特点: TypeScript 是 Microsoft 推出的开源语言,使用 Apache 授权协议 TypeScript 增加了静态类型、类、模块、接口和类型注解 TypeScript 可用于开发大型的应用 TypeScript 易学易于理解
11、请谈谈你所认为 TypeScript 的优缺点;
TypeScript 相比于 JavaScript 的显著优势:
-
静态输入 静态类型化是一种功能,可以在开发人员编写脚本时检测错误。查找并修复错误是当今开发团队的迫切需求。有了这项功能,就会允许开发人员编写更健壮的代码并对其进行维护,以便使得代码质量更好、更清晰。
-
大型的开发项目 有时为了改进开发项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。使用TypeScript工具来进行重构更变的容易、快捷。
-
更好的协作 当开发大型项目时,会有许多开发人员,此时乱码和错误的机也会增加。类型安全是一种在编码期间检测错误的功能,而不是在编译项目时检测错误。这为开发团队创建了一个更高效的编码和调试过程。
-
更强的生产力 干净的 ECMAScript 6 代码,自动完成和动态输入等因素有助于提高开发人员的工作效率。这些功能也有助于编译器创建优化的代码。