ES6新个性
1.ES6引入来严格模式 变量必须申明后在应用 函数的参数不能有同名属性, 否则报错 不能应用with语句 (说实话我根本没用过) 不能对只读属性赋值, 否则报错 不能应用前缀0示意八进制数,否则报错 (说实话我根本没用过) 不能删除不可删除的数据, 否则报错 不能删除变量delete prop, 会报错, 只能删除属性delete global[prop] eval不会在它的外层作用域引入变量 eval和arguments不能被从新赋值 arguments不会主动反映函数参数的变动 不能应用arguments.caller (说实话我根本没用过) 不能应用arguments.callee (说实话我根本没用过) 禁止this指向全局对象 不能应用fn.caller和fn.arguments获取函数调用的堆栈 (说实话我根本没用过) 减少了保留字(比方protected、static和interface)2.对于let和const新增的变量申明3.变量的解构赋值4.字符串的扩大 includes():返回布尔值,示意是否找到了参数字符串。 startsWith():返回布尔值,示意参数字符串是否在原字符串的头部。 endsWith():返回布尔值,示意参数字符串是否在原字符串的尾部。5.数值的扩大 Number.isFinite()用来查看一个数值是否为无限的(finite)。 Number.isNaN()用来查看一个值是否为NaN。6.函数的扩大 函数参数指定默认值7.数组的扩大 扩大运算符8.对象的扩大 对象的解构9.新增symbol数据类型10.Set 和 Map 数据结构 ES6 提供了新的数据结构 Set。它相似于数组,然而成员的值都是惟一的,没有反复的值。 Set 自身是一个构造函数,用来生成 Set 数据结构。 Map它相似于对象,也是键值对的汇合,然而“键”的范畴不限于字符串,各种类型的值(包含对象)都能够当作键。11.Proxy Proxy 能够了解成,在指标对象之前架设一层“拦挡”,外界对该对象的拜访 都必须先通过这层拦挡,因而提供了一种机制,能够对外界的拜访进行过滤和改写。 Proxy 这个词的原意是代理,用在这里示意由它来“代理”某些操作,能够译为“代理器”。 Vue3.0应用了proxy12.Promise Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更正当和更弱小。 特点是: 对象的状态不受外界影响。 一旦状态扭转,就不会再变,任何时候都能够失去这个后果。13.async 函数 async函数对 Generator 函数的区别: (1)内置执行器。 Generator 函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与一般函数截然不同,只有一行。 (2)更好的语义。 async和await,比起星号和yield,语义更分明了。async示意函数里有异步操作,await示意紧跟在前面的表达式须要期待后果。 (3)失常状况下,await命令前面是一个 Promise 对象。如果不是,会被转成一个立刻resolve的 Promise 对象。 (4)返回值是 Promise。 async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象不便多了。你能够用then办法指定下一步的操作。14.Class class跟let、const一样:不存在变量晋升、不能反复申明... ES6 的class能够看作只是一个语法糖,它的绝大部分性能 ES5 都能够做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。15.Module ES6 的模块主动采纳严格模式,不论你有没有在模块头部加上"use strict";。 import和export命令以及export和export default的区别
常见的HTTP申请办法
- GET: 向服务器获取数据;
- POST:将实体提交到指定的资源,通常会造成服务器资源的批改;
- PUT:上传文件,更新数据;
- DELETE:删除服务器上的对象;
- HEAD:获取报文首部,与GET相比,不返回报文主体局部;
- OPTIONS:询问反对的申请办法,用来跨域申请;
- CONNECT:要求在与代理服务器通信时建设隧道,应用隧道进行TCP通信;
- TRACE: 回显服务器收到的申请,次要⽤于测试或诊断。
介绍下 promise 的个性、优缺点,外部是如何实现的,入手实现 Promise
1)Promise根本个性
- 1、Promise有三种状态:pending(进行中)、fulfilled(已胜利)、rejected(已失败)
- 2、Promise对象承受一个回调函数作为参数, 该回调函数承受两个参数,别离是胜利时的回调resolve和失败时的回调reject;另外resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;reject的参数通常是一个Error对象的实例。
- 3、then办法返回一个新的Promise实例,并接管两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)
- 4、catch办法返回一个新的Promise实例
- 5、finally办法不论Promise状态如何都会执行,该办法的回调函数不承受任何参数
- 6、Promise.all()办法将多个多个Promise实例,包装成一个新的Promise实例,该办法承受一个由Promise对象组成的数组作为参数(Promise.all()办法的参数能够不是数组,但必须具备Iterator接口,且返回的每个成员都是Promise实例),留神参数中只有有一个实例触发catch办法,都会触发Promise.all()办法返回的新的实例的catch办法,如果参数中的某个实例自身调用了catch办法,将不会触发Promise.all()办法返回的新实例的catch办法
- 7、Promise.race()办法的参数与Promise.all办法一样,参数中的实例只有有一个率先扭转状态就会将该实例的状态传给Promise.race()办法,并将返回值作为Promise.race()办法产生的Promise实例的返回值
- 8、Promise.resolve()将现有对象转为Promise对象,如果该办法的参数为一个Promise对象,Promise.resolve()将不做任何解决;如果参数thenable对象(即具备then办法),Promise.resolve()将该对象转为Promise对象并立刻执行then办法;如果参数是一个原始值,或者是一个不具备then办法的对象,则Promise.resolve办法返回一个新的Promise对象,状态为fulfilled,其参数将会作为then办法中onResolved回调函数的参数,如果Promise.resolve办法不带参数,会间接返回一个fulfilled状态的 Promise 对象。须要留神的是,立刻resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的完结时执行,而不是在下一轮“事件循环”的开始时。
- 9、Promise.reject()同样返回一个新的Promise对象,状态为rejected,无论传入任何参数都将作为reject()的参数
2)Promise长处
①对立异步 API
- Promise 的一个重要长处是它将逐步被用作浏览器的异步 API ,对立当初各种各样的 API ,以及不兼容的模式和手法。
②Promise 与事件比照
- 和事件相比拟, Promise 更适宜解决一次性的后果。在后果计算出来之前或之后注册回调函数都是能够的,都能够拿到正确的值。 Promise 的这个长处很天然。然而,不能应用 Promise 解决屡次触发的事件。链式解决是 Promise 的又一长处,然而事件却不能这样链式解决。
③Promise 与回调比照
- 解决了回调天堂的问题,将异步操作以同步操作的流程表达出来。
- ④Promise 带来的额定益处是蕴含了更好的错误处理形式(蕴含了异样解决),并且写起来很轻松(因为能够重用一些同步的工具,比方 Array.prototype.map() )。
3)Promise毛病
- 1、无奈勾销Promise,一旦新建它就会立刻执行,无奈中途勾销。
- 2、如果不设置回调函数,Promise外部抛出的谬误,不会反馈到内部。
- 3、当处于Pending状态时,无奈得悉目前停顿到哪一个阶段(刚刚开始还是行将实现)。
- 4、Promise 真正执行回调的时候,定义 Promise 那局部实际上曾经走完了,所以 Promise 的报错堆栈上下文不太敌对。
4)简略代码实现
最简略的Promise实现有7个次要属性, state(状态), value(胜利返回值), reason(错误信息), resolve办法, reject办法, then办法
class Promise{ constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; } }; try { // 立刻执行函数 executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { if (this.state === 'fulfilled') { let x = onFulfilled(this.value); }; if (this.state === 'rejected') { let x = onRejected(this.reason); }; }}
5)面试够用版
function myPromise(constructor){ let self=this; self.status="pending" //定义状态扭转前的初始状态 self.value=undefined;//定义状态为resolved的时候的状态 self.reason=undefined;//定义状态为rejected的时候的状态 function resolve(value){ //两个==="pending",保障了了状态的扭转是不不可逆的 if(self.status==="pending"){ self.value=value; self.status="resolved"; } } function reject(reason){ //两个==="pending",保障了了状态的扭转是不不可逆的 if(self.status==="pending"){ self.reason=reason; self.status="rejected"; } } //捕捉结构异样 try{ constructor(resolve,reject); }catch(e){ reject(e); } }myPromise.prototype.then=function(onFullfilled,onRejected){ let self=this; switch(self.status){ case "resolved": onFullfilled(self.value); break; case "rejected": onRejected(self.reason); break; default: }}// 测试var p=new myPromise(function(resolve,reject){resolve(1)}); p.then(function(x){console.log(x)})//输入1
6)大厂专供版
const PENDING = "pending"; const FULFILLED = "fulfilled"; const REJECTED = "rejected";const resolvePromise = (promise, x, resolve, reject) => { if (x === promise) { // If promise and x refer to the same object, reject promise with a TypeError as the reason. reject(new TypeError('循环援用')) } // if x is an object or function, if (x !== null && typeof x === 'object' || typeof x === 'function') { // If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. let called try { // If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason. let then = x.then // Let then be x.then // If then is a function, call it with x as this if (typeof then === 'function') { // If/when resolvePromise is called with a value y, run [[Resolve]](promise, y) // If/when rejectPromise is called with a reason r, reject promise with r. then.call(x, y => { if (called) return called = true resolvePromise(promise, y, resolve, reject) }, r => { if (called) return called = true reject(r) }) } else { // If then is not a function, fulfill promise with x. resolve(x) } } catch (e) { if (called) return called = true reject(e) } } else { // If x is not an object or function, fulfill promise with x resolve(x) }}function Promise(excutor) { let that = this; // 缓存以后promise实例例对象 that.status = PENDING; // 初始状态 that.value = undefined; // fulfilled状态时 返回的信息 that.reason = undefined; // rejected状态时 回绝的起因 that.onFulfilledCallbacks = []; // 存储fulfilled状态对应的onFulfilled函数 that.onRejectedCallbacks = []; // 存储rejected状态对应的onRejected函数 function resolve(value) { // value胜利态时接管的终值 if(value instanceof Promise) { return value.then(resolve, reject); } // 实际中要确保 onFulfilled 和 onRejected ⽅办法异步执⾏行行,且应该在 then ⽅办法被调⽤用的那⼀一轮事件循环之后的新执⾏行行栈中执⾏行行。 setTimeout(() => { // 调⽤用resolve 回调对应onFulfilled函数 if (that.status === PENDING) { // 只能由pending状态 => fulfilled状态 (防止调⽤用屡次resolve reject) that.status = FULFILLED; that.value = value; that.onFulfilledCallbacks.forEach(cb => cb(that.value)); } }); } function reject(reason) { // reason失败态时接管的拒因 setTimeout(() => { // 调⽤用reject 回调对应onRejected函数 if (that.status === PENDING) { // 只能由pending状态 => rejected状态 (防止调⽤用屡次resolve reject) that.status = REJECTED; that.reason = reason; that.onRejectedCallbacks.forEach(cb => cb(that.reason)); } }); } // 捕捉在excutor执⾏行行器器中抛出的异样 // new Promise((resolve, reject) => { // throw new Error('error in excutor') // }) try { excutor(resolve, reject); } catch (e) { reject(e); }}Promise.prototype.then = function(onFulfilled, onRejected) { const that = this; let newPromise; // 解决理参数默认值 保障参数后续可能持续执⾏行行 onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value; onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason; }; if (that.status === FULFILLED) { // 胜利态 return newPromise = new Promise((resolve, reject) => { setTimeout(() => { try{ let x = onFulfilled(that.value); resolvePromise(newPromise, x, resolve, reject); //新的promise resolve 上⼀一个onFulfilled的返回值 } catch(e) { reject(e); // 捕捉前⾯面onFulfilled中抛出的异样then(onFulfilled, onRejected); } }); }) } if (that.status === REJECTED) { // 失败态 return newPromise = new Promise((resolve, reject) => { setTimeout(() => { try { let x = onRejected(that.reason); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); }); } if (that.status === PENDING) { // 期待态// 当异步调⽤用resolve/rejected时 将onFulfilled/onRejected收集暂存到汇合中 return newPromise = new Promise((resolve, reject) => { that.onFulfilledCallbacks.push((value) => { try { let x = onFulfilled(value); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); that.onRejectedCallbacks.push((reason) => { try { let x = onRejected(reason); resolvePromise(newPromise, x, resolve, reject); } catch(e) { reject(e); } }); }); }};
对事件委托的了解
(1)事件委托的概念
事件委托实质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,父节点能够通过事件对象获取到指标节点,因而能够把子节点的监听函数定义在父节点上,由父节点的监听函数对立解决多个子元素的事件,这种形式称为事件委托(事件代理)。
应用事件委托能够不必要为每一个子元素都绑定一个监听事件,这样缩小了内存上的耗费。并且应用事件代理还能够实现事件的动静绑定,比如说新增了一个子节点,并不需要独自地为它增加一个监听事件,它绑定的事件会交给父元素中的监听函数来解决。
(2)事件委托的特点
- 缩小内存耗费
如果有一个列表,列表之中有大量的列表项,须要在点击列表项的时候响应一个事件:
<ul id="list"> <li>item 1</li> <li>item 2</li> <li>item 3</li> ...... <li>item n</li></ul>
如果给每个列表项一一都绑定一个函数,那对于内存耗费是十分大的,效率上须要耗费很多性能。因而,比拟好的办法就是把这个点击事件绑定到他的父层,也就是 ul 上,而后在执行事件时再去匹配判断指标元素,所以事件委托能够缩小大量的内存耗费,节约效率。
- 动静绑定事件
给上述的例子中每个列表项都绑定事件,在很多时候,须要通过 AJAX 或者用户操作动静的减少或者去除列表项元素,那么在每一次扭转的时候都须要从新给新增的元素绑定事件,给行将删去的元素解绑事件;如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和指标元素的增减是没有关系的,执行到指标元素是在真正响应执行事件函数的过程中去匹配的,所以应用事件在动静绑定事件的状况下是能够缩小很多反复工作的。
// 来实现把 #list 下的 li 元素的事件代理委托到它的父层元素也就是 #list 上:// 给父层元素绑定事件document.getElementById('list').addEventListener('click', function (e) { // 兼容性解决 var event = e || window.event; var target = event.target || event.srcElement; // 判断是否匹配指标元素 if (target.nodeName.toLocaleLowerCase === 'li') { console.log('the content is: ', target.innerHTML); }});
在上述代码中, target 元素则是在 #list 元素之下具体被点击的元素,而后通过判断 target 的一些属性(比方:nodeName,id 等等)能够更准确地匹配到某一类 #list li 元素之上;
(3)局限性
当然,事件委托也是有局限的。比方 focus、blur 之类的事件没有事件冒泡机制,所以无奈实现事件委托;mousemove、mouseout 这样的事件,尽管有事件冒泡,然而只能一直通过地位去计算定位,对性能耗费高,因而也是不适宜于事件委托的。
当然事件委托不是只有长处,它也是有毛病的,事件委托会影响页面性能,次要影响因素有:
- 元素中,绑定事件委托的次数;
- 点击的最底层元素,到绑定事件元素之间的
DOM
层数;
在必须应用事件委托的中央,能够进行如下的解决:
- 只在必须的中央,应用事件委托,比方:
ajax
的部分刷新区域 - 尽量的缩小绑定的层级,不在
body
元素上,进行绑定 - 缩小绑定的次数,如果能够,那么把多个事件的绑定,合并到一次事件委托中去,由这个事件委托的回调,来进行散发。
代码输入问题
window.number = 2;var obj = { number: 3, db1: (function(){ console.log(this); this.number *= 4; return function(){ console.log(this); this.number *= 5; } })()}var db1 = obj.db1;db1();obj.db1();console.log(obj.number); // 15console.log(window.number); // 40
这道题目看清起来有点乱,然而实际上是考查this指向的:
- 执行db1()时,this指向全局作用域,所以window.number 4 = 8,而后执行匿名函数, 所以window.number 5 = 40;
- 执行obj.db1();时,this指向obj对象,执行匿名函数,所以obj.numer * 5 = 15。
说一下怎么把类数组转换为数组?
//通过call调用数组的slice办法来实现转换Array.prototype.slice.call(arrayLike)//通过call调用数组的splice办法来实现转换Array.prototype.splice.call(arrayLike,0)//通过apply调用数组的concat办法来实现转换Array.prototype.concat.apply([],arrayLike)//通过Array.from办法来实现转换Array.from(arrayLike)
参考 前端进阶面试题具体解答
代码输入后果
Promise.resolve('1') .then(res => { console.log(res) }) .finally(() => { console.log('finally') })Promise.resolve('2') .finally(() => { console.log('finally2') return '我是finally2返回的值' }) .then(res => { console.log('finally2前面的then函数', res) })
输入后果如下:
1finally2finallyfinally2前面的then函数 2
.finally()
个别用的很少,只有记住以下几点就能够了:
.finally()
办法不论Promise对象最初的状态如何都会执行.finally()
办法的回调函数不承受任何的参数,也就是说你在.finally()
函数中是无奈晓得Promise最终的状态是resolved
还是rejected
的- 它最终返回的默认会是一个上一次的Promise对象值,不过如果抛出的是一个异样则返回异样的Promise对象。
- finally实质上是then办法的特例
.finally()
的谬误捕捉:
Promise.resolve('1') .finally(() => { console.log('finally1') throw new Error('我是finally中抛出的异样') }) .then(res => { console.log('finally前面的then函数', res) }) .catch(err => { console.log('捕捉谬误', err) })
输入后果为:
'finally1''捕捉谬误' Error: 我是finally中抛出的异样
代码输入后果
function Person(name) { this.name = name}var p2 = new Person('king');console.log(p2.__proto__) //Person.prototypeconsole.log(p2.__proto__.__proto__) //Object.prototypeconsole.log(p2.__proto__.__proto__.__proto__) // nullconsole.log(p2.__proto__.__proto__.__proto__.__proto__)//null前面没有了,报错console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)//null前面没有了,报错console.log(p2.constructor)//Personconsole.log(p2.prototype)//undefined p2是实例,没有prototype属性console.log(Person.constructor)//Function 一个空函数console.log(Person.prototype)//打印出Person.prototype这个对象里所有的办法和属性console.log(Person.prototype.constructor)//Personconsole.log(Person.prototype.__proto__)// Object.prototypeconsole.log(Person.__proto__) //Function.prototypeconsole.log(Function.prototype.__proto__)//Object.prototypeconsole.log(Function.__proto__)//Function.prototypeconsole.log(Object.__proto__)//Function.prototypeconsole.log(Object.prototype.__proto__)//null
这道义题目考查原型、原型链的根底,记住就能够了。
代码输入后果
async function async1 () { console.log('async1 start'); await new Promise(resolve => { console.log('promise1') }) console.log('async1 success'); return 'async1 end'}console.log('srcipt start')async1().then(res => console.log(res))console.log('srcipt end')
输入后果如下:
script startasync1 startpromise1script end
这里须要留神的是在async1
中await
前面的Promise是没有返回值的,也就是它的状态始终是pending
状态,所以在await
之后的内容是不会执行的,包含async1
前面的 .then
。
代码输入后果
function foo() { console.log( this.a );}function doFoo() { foo();}var obj = { a: 1, doFoo: doFoo};var a = 2; obj.doFoo()
输入后果:2
在Javascript中,this指向函数执行时的以后对象。在执行foo的时候,执行环境就是doFoo函数,执行环境为全局。所以,foo中的this是指向window的,所以会打印出2。
setInterval 模仿 setTimeout
形容:应用setInterval
模仿实现setTimeout
的性能。
思路:setTimeout
的个性是在指定的工夫内只执行一次,咱们只有在setInterval
外部执行 callback
之后,把定时器关掉即可。
实现:
const mySetTimeout = (fn, time) => { let timer = null; timer = setInterval(() => { // 敞开定时器,保障只执行一次fn,也就达到了setTimeout的成果了 clearInterval(timer); fn(); }, time); // 返回用于敞开定时器的办法 return () => clearInterval(timer);}// 测试const cancel = mySetTimeout(() => { console.log(1);}, 1000); // 一秒后打印 1
说一下vue3.0你理解多少?
<!-- 响应式原理的扭转 Vue3.x 应用Proxy取代 Vue2.x 版本的Object.defineProperty --> <!-- 组件选项申明形式Vue3.x 应用Composition API setup 是Vue3.x新增的一个选项,他 是组件内应用Composition API 的入口 --> <!-- 模板语法变动slot具名插槽语法 自定义指令 v-model 降级 --> <!-- 其它方面的更改Suspense反对Fragment(多个根节点) 和Protal (在dom其余局部渲染组建内容)组件 针对一些非凡的场景做了解决。基于treeshaking优化,提供了更多的内置性能。 -->
代码输入后果
function runAsync (x) { const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000)) return p}Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res))
输入后果如下:
123[1, 2, 3]
首先,定义了一个Promise,来异步执行函数runAsync,该函数传入一个值x,而后距离一秒后打印出这个x。
之后再应用Promise.all
来执行这个函数,执行的时候,看到一秒之后输入了1,2,3,同时输入了数组[1, 2, 3],三个函数是同步执行的,并且在一个回调函数中返回了所有的后果。并且后果和函数的执行程序是统一的。
Promise.race
形容:只有promises
中有一个率先扭转状态,就返回这个率先扭转的Promise
实例的返回值。
实现:
Promise.race = function(promises){ return new Promise((resolve, reject) => { if(Array.isArray(promises)) { if(promises.length === 0) return resolve(promises); promises.forEach((item) => { Promise.resolve(item).then( value => resolve(value), reason => reject(reason) ); }) } else return reject(new TypeError("Argument is not iterable")); });}
异步任务调度器
形容:实现一个带并发限度的异步调度器 Scheduler,保障同时运行的工作最多有 limit
个。
实现:
class Scheduler { queue = []; // 用队列保留正在执行的工作 runCount = 0; // 计数正在执行的工作个数 constructor(limit) { this.maxCount = limit; // 容许并发的最大个数 } add(time, data){ const promiseCreator = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(data); resolve(); }, time); }); } this.queue.push(promiseCreator); // 每次增加的时候都会尝试去执行工作 this.request(); } request() { // 队列中还有工作才会被执行 if(this.queue.length && this.runCount < this.maxCount) { this.runCount++; // 执行先退出队列的函数 this.queue.shift()().then(() => { this.runCount--; // 尝试进行下一次工作 this.request(); }); } }}// 测试const scheduler = new Scheduler(2);const addTask = (time, data) => { scheduler.add(time, data);}addTask(1000, '1');addTask(500, '2');addTask(300, '3');addTask(400, '4');// 输入后果 2 3 1 4
说一下常见的检测数据类型的几种形式?
typeof 其中数组、对象、null都会被判断为Object,其余判断都正确instanceof 只能判断援用数据类型,不能判断根本数据类型constructor 它有2个作用 一是判断数据的类型,二是对象实例通过constructor对象拜访它的构造函数。须要留神的事件是如果创立一个对象来扭转它的原型,constructor就不能来判断数据类型了Object.prototype.toString.call()
Number() 的存储空间是多大?如果后盾发送了一个超过最大本人的数字怎么办
Math.pow(2, 53) ,53 为有效数字,会产生截断,等于 JS 能反对的最大数字。
Promise.allSettled
形容:等到所有promise
都返回后果,就返回一个promise
实例。
实现:
Promise.allSettled = function(promises) { return new Promise((resolve, reject) => { if(Array.isArray(promises)) { if(promises.length === 0) return resolve(promises); let result = []; let count = 0; promises.forEach((item, index) => { Promise.resolve(item).then( value => { count++; result[index] = { status: 'fulfilled', value: value }; if(count === promises.length) resolve(result); }, reason => { count++; result[index] = { status: 'rejected'. reason: reason }; if(count === promises.length) resolve(result); } ); }); } else return reject(new TypeError("Argument is not iterable")); });}
Object.is 实现
题目形容:
Object.is不会转换被比拟的两个值的类型,这点和===更为类似,他们之间也存在一些区别。 1. NaN在===中是不相等的,而在Object.is中是相等的 2. +0和-0在===中是相等的,而在Object.is中是不相等的
实现代码如下:
Object.is = function (x, y) { if (x === y) { // 当前情况下,只有一种状况是非凡的,即 +0 -0 // 如果 x !== 0,则返回true // 如果 x === 0,则须要判断+0和-0,则能够间接应用 1/+0 === Infinity 和 1/-0 === -Infinity来进行判断 return x !== 0 || 1 / x === 1 / y; } // x !== y 的状况下,只须要判断是否为NaN,如果x!==x,则阐明x是NaN,同理y也一样 // x和y同时为NaN时,返回true return x !== x && y !== y;};
大数相加
题目形容:实现一个add办法实现两个大数相加
let a = "9007199254740991";let b = "1234567899999999999";function add(a ,b){ //...}
实现代码如下:
function add(a ,b){ //取两个数字的最大长度 let maxLength = Math.max(a.length, b.length); //用0去补齐长度 a = a.padStart(maxLength , 0);//"0009007199254740991" b = b.padStart(maxLength , 0);//"1234567899999999999" //定义加法过程中须要用到的变量 let t = 0; let f = 0; //"进位" let sum = ""; for(let i=maxLength-1 ; i>=0 ; i--){ t = parseInt(a[i]) + parseInt(b[i]) + f; f = Math.floor(t/10); sum = t%10 + sum; } if(f!==0){ sum = '' + f + sum; } return sum;}