@wy
2018-09-27T18:01:03.000000Z
字数 4569
阅读 483
面试题
async 关键字是用来创建异步函数,调用后,会隐式的返回一个 Promise 对象作为结果。
await 是一个操作符,只能使用在 async function 的异步函数中,作用是暂停当前 async function继续执行,等待 Promise 处理完成。Promise 处理完之后,把resolve函数参数或者异常原因作为 await 表达式的值。
如果在代码中使用了异步函数,它的语法和结构会更像是标准的同步函数。
console.log不是标准化的,所以行为是相当未定义的(不是异步,或许是同步执行的,没有明确规定),控制台可能克隆(序列化)您记录的可变对象,或者它将存储对它们的引用。控制台中的初始渲染可能会显示对象的“当前”状态。但是,当展开对象以进一步检查其属性时,控制台很可能只会存储对对象及其属性的引用,并且现在显示它们将显示它们的当前(已经变异的)状态。
参考:https://stackoverflow.com/questions/23392111/console-log-async-or-sync
bind是用来改变函数this指向的,但不像 call 和 apply那样,会把函数直接执行,bind执行后会返回新的函数。所以实现起来不是那么的麻烦。
但是有一点要主要,将来bind返回的函数如果当做构造函数的话,是需要继承原来调用bind的那个函数的。
可以先看下bind的常规用处:
function func(...arg){
console.log('改变this为:',this);
console.log('参数为:',arg);
}
// bind第一个参数是改变this指向,改变为数组,之后传入的是给func函数传递的实参
let f = func.bind([1,2,3],1,2,3);
// 调用f
f(4,5,6); // 结果为:改变this为: [1, 2, 3],同时给func传入参数
// 参数为: [1, 2, 3, 4, 5, 6]
把f当做构造函数,此时要找原型上的方法,依然去func上找:
function func(...arg){
console.log('改变this为:',this);
console.log('参数为:',arg);
}
func.prototype.say = function (){
console.log('会说话');
}
// bind第一个参数是改变this指向,改变为数组,之后传入的是给func函数传递的实参
let f = func.bind([1,2,3],1,2,3);
let instance = new f(); // this不在执行传入的数组,而是实例本身
instance.say(); // 打印:会说话
以上要注意两点:
实现代码如下:
Function.prototype.customeBind = function (argThis,...arg){
let self = this; // this指向调用customeBind的函数
let m = function (){}
let fnBound = function (...arg2){
// 判断是否是new调用创建实例
let that = this instanceof m ? this : argThis;
return self.apply(that,[...arg,...arg2])
}
m.prototype = self.prototype;
fnBound.prototype = new m;
return fnBound;
}
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
作用:会将传入的字符串当做 JavaScript 代码进行执行
语法:eval(string)
说明:string是有效 JavaScript 代码。
安全问题: 当使用不可信任来源的代码时,谨慎使用 eval 解析。
缺点:
1. 可读性差
2. 不利于调试
3. 增加性能消耗
4. 破坏执行作用域
补充说明:
let s = '({"b":20,a:90})'
console.log(eval(s));
现在使用JSON.parse代替。
var a = 10; // 全局变量
let js = 'var a = 10000; console.log(a);'
function test(){
var b = 30;
eval(js); // 执行后在全局重新定义了变量a
eval('var b = 50;'); // 执行后覆盖局部的变量b
console.log(b); // 输出为50
}
test();
console.log(a); // 结果为10000
执行代码后并不是在局部定义变量,而是在全局定义了变量 a
执行代码后在局部重新定义了b变量,把局部变量覆盖了。
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms
首先需要了解parseInt的完整用法:
作用:解析一个字符串参数,并返回一个指定基数的十进制的整数
语法:parseInt(string, radix);
说明:radix一个介于2和36之间的整数,标示string字符串的基数。默认这个基数是10
例如:
parseInt('100', 10); 结果为:100
意思是把100通过基数10转成10进制的数字,结果还是100
数字100,从右到左从低位到高位,位置从0开始,依次乘上10为基数的次方,然后加上总和:
1*10^2 + 0*10^1 + 0*10^0 = 100 + 0 + 0 = 100;
parseInt('100', 2); 结果为:4
意思是把1000通过基数2转成10进制的数字,如下操作,把数字转成10进制:
数字100,从右到左从低位到高位,位置从0开始,依次乘上2为基数的次方,然后加上总和:
1*2^2 + 0*2^1 + 0*2^0 = 4 + 0 + 0 = 4;
parseInt('100', 3); 结果为:9
意思是把1000通过基数3转成10进制的数字,如下操作,把数字转成10进制:
数字100,从右到左从低位到高位,位置从0开始,依次乘上3为基数的次方,然后加上总和:
1*3^2 + 0*3^1 + 0*3^0 = 6 + 3 + 0 = 9;
一直到基数为36都成立。。。
但是要注意,传入的数字每一位不能大于等于基数,否则返回NaN,例如:
parseInt('200', 2); 结果为:NaN
parseInt('301', 3); 结果为:NaN
再说map方法的使用,主要是map回调函数的使用
[1,2,3].map((item,index) => {
这个回调函数接收的是每一项item,和下标index
})
回到题再来看一下,["1","2","3"].map(parseInt)
使用map循环数组,传入parseInt,此时parseInt会接受两个参数,每一项和下标,就类似这样:
["1","2","3"].map(function parseInt(item,index){
...
})
具体到调用parseInt接收的参数:
parseInt('1',0) // 基数不能为0,直接返回前面数字 结果为1
parseInt('2',1) // 基数为1,前面数字位数有大于1的,结果为NaN
parseInt('3',2) // 基数为2,前面数字位数有大于2的,结果为NaN
map返回值是数组,所以最终结果为: [1,NaN,NaN]
函数默认参数
模板字符串
扩展运算符...
解构赋值
箭头函数 =>
Promise对象解决异步回调
块级作用域的let和const
类class,继承extend
模块化es6 module
Cache-Control 通用消息头被用于在http 请求和响应中通过指定指令来实现缓存机制。
指令不区分大小写,并且具有可选参数,可以用令牌或者带引号的字符串语法。多个指令以逗号分隔。
可缓存性
public
表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
private
表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它),可以缓存响应内容。
no-cache
在释放缓存副本之前,强制高速缓存将请求提交给原始服务器进行验证。
no-cache 无论在 HTTP/1.0 下还是在 HTTP/1.1 都不代表“每次请求页面时都不要读缓存”, 而是无论本地副本是否过期都需要校验, 在校验本地副本与资源服务器一致时,使用本地副本。
到期
max-age=< seconds>
设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。
no-store
缓存不应存储有关客户端请求或服务器响应的任何内容。
参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ#%E7%BC%93%E5%AD%98%E6%8E%A7%E5%88%B6
务端可以通过响应头里的 Last-Modified(最后修改时间) 或者 ETag(内容特征) 标记实体。浏览器会存下这些标记,并在下次请求时带上 If-Modified-Since: 上次 Last-Modified 的内容 或 If-None-Match: 上次 ETag 的内容,询问服务端资源是否过期。如果服务端发现并没有过期,直接返回一个状态码为 304、正文为空的响应,告知浏览器使用本地缓存;如果资源有更新,服务端返回状态码 200、新的 Last-Modified、Etag 和正文。这个过程被称之为 HTTP 的协商缓存,通常也叫做弱缓存。
Last-Modified的问题:
1. 只能精确到秒,1 秒内的多次变化反映不出来;
2. 在轮询的负载均衡算法中,如果各机器读到的文件修改时间不一致,有缓存无故失效和缓存不更新的风险。
HTTP/1.1 并没有规定 ETag 的生成规则,而一般实现者都是对资源内容做摘要,能解决前面两个问题。
服务端通过响应头告诉浏览器,在什么时间之前(Expires)或在多长时间之内(Cache-Control: Max-age=xxx),不要再请求服务器了。这个机制我们通常称之为 HTTP 的强缓存。
使用 Cache-Control: