请说出下列代码最终的执行结果,并解释为什么?
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
}
}
a[6]();
最终执行结果为:打印 10。
原因:for 循环时是使用 var 定义循环变量 i (存在变量提升),然后依次为 a 数组元素赋值为一个函数,函数内打印 i;循环结束后调用 a[6]() ,相当于在全局环境下打印 i,而此时 i 已经变为 10。
请说出下列代码最终的执行结果,并解释为什么?
var temp = 123;
if (true) {
console.log(tmp);
let tmp;
}
最终执行结果为:报出引用错误,在初始化之前不能访问 'tmp'。
原因是因为,块级作用域内使用了 let/const 关键字声明变量,就存在暂时性死区,在声明之前使用这些变量会报错。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
结合 ES6 新语法,用最简单的方式找出数组中的最小值?
var arr = [12, 34, 32, 89, 4];
答案: Math.min(...arr)
请详细说明 var,let,const 三种声明变量的方式之间的具体差别?
1.使用var声明变量
2.使用let声明变量
3.使用const声明常量
请说出下列代码最终的执行结果,并解释为什么?
var a = 10;
var obj = {
a: 20,
fn() {
setTimeout(() => {
console.log(this.a);
});
}
};
obj.fn();
最终执行结果为:打印出 20。
原因:setTimeout的回调是一个箭头函数,箭头函数不会改变this的指向。this始终指向沿着作用域往上找的第一个 function ,看这个 function 最终是怎样调用的。题目里是这样调用的 obj.fn() , 所以此时fn内的this指向obj。
简述 Symbol 类型的用途?
Symbol 是 ES2015 提出的一种新的原始数据类型,主要用途有:
说说什么是浅拷贝?什么是深拷贝?
引用类型的数据在赋值的过程中,其实是拷贝了内存地址,比如将b对象赋值给a变量,这两个变量都指向了同一个内存地址,修改了a变量之后b对象也会跟着改变。而我们希望得到的是,修改a不会影响b,这两个对象不会相互影响,针对这种场景就可以使用浅拷贝和深拷贝。
浅拷贝是指将对象的所有属性值拷贝到新的对象,进行一层属性的拷贝,但是如果属性值也是对象的话,依旧是拷贝那个对象的地址,上面的问题还是会出现。这种情况就可以使用深拷贝来解决,即使属性值是对象,深拷贝也可以做到无限层级拷贝,切断两个引用类型变量之间的关系,不会相互影响。
浅拷贝的方法:遍历对象属性赋值,Object.assign(),展开运算符...
深拷贝的方法:浅拷贝+递归,JSON.parse(JSON.stringify(obj))
JSON.parse(JSON.stringify())这个方法有一定的局限性:
序列化时遇到如下情况需要注意:
终极深拷贝的方法可以参考 lodash 的深拷贝,不过日常开发如果没遇到以上的情况,用 JSON.parse(JSON.stringify()) 足以...
谈谈你是如何理解 JS 异步编程的,EventLoop 是做什么的,什么是宏任务,什么是微任务?
js是单线程的,同一时间只能做一件事,两段JS不能同时执行,主要原因是要避免dom渲染的冲突。解决方案就是异步,而异步编写的代码,没按照书写方式执行,callback过多,导致可读性很差,难以理解,所以就出现了 promise / async await。
EventLoop 指事件轮询,是js实现异步的具体解决方案。同步代码,在主线程(调用栈 Call stack)中直接执行,压栈-弹栈。异步任务会依次放入消息队列(Queue)中,EventLoop 会监听调用栈和消息队列,当调用栈中的代码执行完之后,它会拿消息队列中的第一个任务放到调用栈执行,以此类推。
异步任务可以分为宏任务和微任务,这两个任务的执行顺序不同。宏任务会依次放入消息队列等待事件轮询去执行,而微任务是放在本次调用栈的末尾去执行,也就是说,微任务比宏任务先执行。
将下面异步代码使用 Promise 改进?
setTimeout(function () {
var a = 'hello ';
setTimeout(function () {
var b = 'lagou ';
setTimeout(function () {
var c = 'I Love U';
console.log(a + b + c);
}, 10);
}, 10);
}, 10);
答:
function task (msg) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(msg);
}, 10);
});
};
task('hello ')
.then(msg => task(msg + 'lagou '))
.then(msg => task(msg + 'I Love U'))
.then(msg => console.log(msg));
请简述 TypeScript 与 JavaScript 之间的关系?
TypeScript 是 JavaScript 的一个超集(扩展集),就是在 JS 的基础上多出一些扩展特性,这些扩展特性包括:强大的类型系统、对 ES6+ 的良好支持。TS 最终会被编译为 JS 运行。
请谈谈你所认为的 TypeScript 优缺点?
优点:
缺点:
来自:https://segmentfault.com/a/1190000022744098
javascript中alert是Bom中的成员函数,alert对话框是模态的,具有阻塞性质的,不点击是不会执行后续代码的。js的阻塞是指在调用结果返回之前,当前线程会被挂起, 只有在得到结果之后才会继续执行。
如何优化async代码?更好的编写async函数:使用return Promise.reject()在async函数中抛出异常,让相互之间没有依赖关系的异步函数同时执行,不要在循环的回调中/for、while循环中使用await,用map来代替它
Javascript语言的执行环境是单线程,异步模式非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。
js异步加载又被称为非阻塞加载,浏览器在下载JS的同时,还会进行后续页面处理。那么如何实现js异步加载呢?下面整理了多种实现方案供大家参考。异步加载js方案:Script Dom Element、onload时的异步加载、$(document).ready()、async属性、defer属性、es6模块type=module属性
回调函数方式:将异步方法如readFile封装到一个自定义函数中,通过将异步方法得到的结果传给自定义方法的回调函数参数。事件驱动方式:使用node events模块,利用其EventEmitter对象
JavaScript引擎是基于单线程 (Single-threaded) 事件循环的概念构建的,同一时刻只允许一个代码块在执行,所以需要跟踪即将运行的代码,那些代码被放在一个任务队列 (job queue) 中
传统的异步解决方案采用回调函数和事件监听的方式,而这里主要记录两种异步编程的新方案:ES6的新语法Promise;ES2017引入的async函数;Generator函数(略)
JS本身是一门单线程的语言,所以在执行一些需要等待的任务(eg.等待服务器响应,等待用户输入等)时就会阻塞其他代码。如果在浏览器中JS线程阻塞了,浏览器可能会失去响应,从而造成不好的用户体验。
请实现如下的函数,可以批量请求数据,所有的URL地址在urls参数中,同时可以通过max参数 控制请求的并发度。当所有的请求结束后,需要执行callback回调。发请求的函数可以直接使用fetch。
将setState()认为是一次请求而不是一次立即执行更新组件的命令。为了更为可观的性能,React可能会推迟它,稍后会一次性更新这些组件。React不会保证在setState之后,能够立刻拿到改变的结果。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!