91.实现一个 promise
参考链接:实现一个完美符合Promise/A+规范的Promise · Issue #4 · forthealllight/blog · GitHub
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的原型上定义链式调用的then方法
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:
}
}
92.Function.proto(getPrototypeOf)
获取一个对象的原型,在 chrome 中可以通过proto的形式,或者在 ES6 中可以通过 Object.getPrototypeOf 的形式。
Function.proto 说明 Function 由什么对象继承而来:
Function.__proto__ == Object.prototype; // false
Function.__proto__ == Function.prototype; // true
说明 Function 的原型也是 Function
93.数组常用方法
push() 和 unshift():向数组的 尾部/头部 添加若干元素,并返回 数组的 新长度;
var arr = [1, 2];
// 向末尾追加元素
arr.push(3, 4); // arr = [1,2,3,4];
// 向开头追加元素
arr.unshift(6, 7); // arr = [6,7,1,2,3,4];
pop() 和 shift():从数组的 尾部/头部 删且只删1个元素;空数组是继续删除,且不报错,返回undefined
// 删除末尾元素
arr.pop(); // arr = [6,7,1,2,3];
// 删除开头元素
arr.shift(); // arr = [7,1,2,3]
splice() 方法用于添加或删除数组中的元素,会改变原始数组。
slice() 方法可从已有的数组中返回选定的元素,可提取字符串的某个部分,并以新的字符串返回被提取的部分,不会改变原始数组。
94.数组去重
参考文章:JavaScript中数组去重的几种方法(双循环去重、indexOf去重、相邻元素去重、对象属性去重、set与解构赋值去重、set与Array.form去重)_indexof循环去重_谁是听故事的人的博客-CSDN博客
1.indexOf 循环去重:
返回某个指定的元素在数组中首次出现的位置:定义一个空数组res,调用 indexOf() 方法对原来的数组进行遍历,如果元素不在res中,将其 push 进res中,最后将res返回即可获得去重的数组(判断新数组中是否有a[i],如果没有indexOf,返回-1,把a[i]放入新数组中)
var res = []
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) == -1) {
res.push(arr[i]);
}
}
return res;
2.ES6 Set 去重:
var newArr = Array.from(new Set(arr));
3.Object 键值对去重:
把数组的值存成 Object 的 key 值,比如 Object[val1] = true, 在判断另一个值的时候,如果 Object[val2] 存在,说明该值重复
95.去除字符串首尾空格:使用正则(^\s)|(\s$)
96.性能优化
通过 减少 HTTP 请求;使用内容发布网络(CDN);添加本地缓存;压缩资源文件;将 CSS 样式表放在顶部;把 javascript 放在底部(浏览器的运行机制决定);避免使用 CSS 表达式;减少 DNS 查询;使用外部 javascript 和 CSS;避免重定向;图片懒加载等。
97.跨域的原理
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 js 实施的安全限制,只要协议、域名、端口有任一不同,都被当作不同的域。简而言之,跨域原理即是通过各种方式,避开浏览器的安全限制。
98.暂停死区:在代码块内,使用 let、const 命令声明变量之前,该变量都是不可用的。
99.游戏《Flappy Bird》:一只小鸟在飞,前面是无尽的沙漠,上下不断有钢管生成,要躲避钢管。在玩这个游戏时总出现卡顿甚至崩溃,其原因以及解决办法:
这是单机游戏,回答与网络无关
1.内存溢出问题:在钢管离开可视区域后,销毁钢管;不断生成钢管且不及时清理,容易内存溢出从而游戏崩溃,因此可通过垃圾收集器回收钢管。
2.资源过大问题:选择图片文件更小的图片格式,比如 webp、png 格式,因为绘制图片需要较大计算量。
3.资源加载问题:在可视区域之前预加载好资源,如果在可视区域生成钢管的话,用户认为钢管是卡顿后才生成的,用户体验不流畅。
4.canvas 绘制频率问题:大部分显示器刷新频率为 60 次/s,因此游戏的每一帧绘制间隔时间需要小于 1000/60=16.7ms,才能实现不卡顿。
100.按需加载
当用户触发了动作时才加载对应的功能。触发的动作要看具体的业务场景,包括但不限于:鼠标点击、输入文字、拉动滚动条,鼠标移动、窗口大小更改等。加载的文件可以是 JS、图片、CSS、HTML 等。
101.说一下什么是 virtual dom
用 JavaScript 对象结构表示 DOM 树的结构,用这个树构建一个真正的 DOM 树,插到文档中, 当状态变更的时候,重新构造一棵新的对象树。将新树和旧树比较,记录差异,应用到所构建的真正 DOM 树,从而实现视图更新。Virtual DOM 本质上是在 JS 和 DOM 之间做一个缓存。
102.JS 原型链
JS 通过原型实现继承,在 JS 中,一个构造函数默认有一个 prototype 属性,它是一个对象, 同时这个 prototype 对象自带有一个 constructor 属性,这个属性指向这个构造函数,同时每一个实例都会有一个proto属性指向这个 prototype 对象,把这个叫做隐式原型。在使用一个实例方法时,会先检查这个实例中是否有这个方法,没有的话会检查这个 prototype 对象是否有这个方法,基于这个规则,如果让原型对象指向另一个类型的实例,即 constructor1.protoytpe = instance2,如果引用 constructor1 构造的实例 instance1 的某个属性 p1,会先在 instance1 内部属性中找,接着在 instance1.proto(constructor1.prototype)即 instance2 中寻找 p1
搜寻轨迹:instance1->instance2->constructor2.prototype……->Object.prototype 即原型链
原型链顶端是 Object.prototype
103.Promise 回调链
Promise 能够在回调函数里使用 return 和 throw, 所以在 then 中可以 return 出一个 promise 对象或其他值,也可以 throw 出一个错误对象;如果没有 return,将默认返回 undefined,后面的 then 中的回调参数接收到的是 undefined。
104.async 和异步
用法:async 表示这是一个 async 函数,await 只能用在这个函数里面。
await 表示在这里等待异步操作返回结果,再继续执行。 await 后一般是一个 promise 对象
示例:async 用于定义一个异步函数,该函数返回一个 Promise。 如果 async 函数返回的是一个同步的值,这个值将被包装成 resolve 的 Promise,等同于 return Promise.resolve(value)。
await 用于一个异步操作之前,表示要 “等待” 这个异步操作的返回值。await 也可以用于一个同步的值。
105.ES6,ES7 的语法:promise,await/async,let、const、块级作用域、箭头函数
106.promise 和 await/async 的关系:异步编程的解决方案