1- js 是单线程还是多线程?
单线程,单位时间内只能处理一个进程
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事,为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完 全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
2-let 和 var 声明变量的区别?
js中let和var定义变量的区别,主要体现在作用于的不同。
var定义的变量是全局变量或者函数变量。
let定义的变量是块级的变量。
例如:
while(1){
let let1 = 2;
var var1 = 2;
}
alert(let1); //不可访问
alert(var1); //可以访问
也就是说,let只对它所在的最内侧块内有效,而var的范围至少是一个函数之内。
var定义的变量是全局变量或者函数变量。
let定义的变量是块级的变量。
例如:
while(1){
let let1 = 2;
var var1 = 2;
}
alert(let1); //不可访问
alert(var1); //可以访问
也就是说,let只对它所在的最内侧块内有效,而var的范围至少是一个函数之内。
3- 说说 async/await 的使用方式和场景:
我们开发过程中,经常会使用到Promise,它很好的解决了异步问题。但是,在业务逻辑比较复杂的情况下,单纯的使用Promise并不好用。这时,我们可以使用ES7中新添加的async/await,在async标记的函数中,如果遇到await表达式,则函数会等待await标记的Promise解析完成,然后才会继续执行下面的代码。
那么,我们来举几个例子看看什么时候比较适合使用async/await:
那么,我们来举几个例子看看什么时候比较适合使用async/await:
假设我们有如下两个方法:
function convertToBase64Data(url) { // 转成base64格式 return new Promise( resolve => { setTimeout( () => { resolve('img'); }, 1000); }); } function saveToLocal(img) { // 保存到本地 return new Promise( resolve=> { setTimeout( () => { resolve('success'); }, 200); }); }
场景1:多个异步需要按顺序:图片处理完成然后保存在本地
function fn1() { return convertToBase64Data('http://1.jpg').then( base64Data => { return saveToLocal(base64Data); }) }
使用await则更简洁:
async function fn1() { const base64Data = await download('http://1.jpg'); const result = await saveToLocal(base64Data); return result; }
场景2:图片需要同时处理,但是要按顺序一张一张保存在本地:
不使用await:
function fn2() { const promise1 = convertToBase64Data('http://1.jpg'); const promise2 = convertToBase64Data('http://1.jpg'); Promise.all([promise1,promise2]).then( datas => { saveToLocal(datas[0]).then( result1 => { saveToLocal(datas[1]).then(result2 => { console.log(result2); }) }) }) }
我们看到,回调很多,很不方便,下面是使用await:
async function fn2() { // 同时处理两张 const promise1 = convertToBase64Data('http://1.jpg'); const promise2 = convertToBase64Data('http://2.jpg'); const [data1, data2] = await Promise.all([promise1, promise2]); // 先保存第一张 const result = await saveToLocal(data1); // 再保存第二张 const result2 = await saveToLocal(data2); }
条件语句
不使用await:
function fn4(needConvertToBase64) { return download('http://1.jpg').then( img => { if (needConvertToBase64) { return convertToBase64(img).then(base64Data => { return base64Data; }); } else { return img; } }); }
await:
async function fn4(needConvertToBase64) { const img = await download('http://1.jpg'); if (needConvertToBase64) { const base64Data = await convertToBase64(img); return base64Data; } return img; }
4- 谈谈对 promise 的理解:
Promise是最早由社区提出和实现的一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和更强大。
ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
产生:
promise是为解决异步处理回调金字塔问题而产生的
特点:
Promise对象的状态不受外界影响
pending 初始状态
fulfilled 成功状态
rejected 失败状态
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态.
Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected;
缺点:
无法取消Promise,一旦新建它就会立即执行,无法中途取消
如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
5- 箭头函数有什么作用和实际应用场景?
- 箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如:用在 map、reduce、filter 的回调函数定义中
- 箭头函数的亮点是简洁,但在有多层函数嵌套的情况下,箭头函数反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数
- 箭头函数要实现类似纯函数的效果,必须剔除外部状态。所以箭头函数不具备普通函数里常见的 this、arguments 等,当然也就不能用 call()、apply()、bind() 去改变 this 的指向
-
箭头函数不适合定义对象的方法(对象字面量方法、对象原型方法、构造器方法),因为箭头函数没有自己的 this,其内部的 this 指向的是外层作用域的 this