下面代码中 a 在什么情况下会打印 1?
var a = ?;
if(a == 1 && a == 2 && a == 3){
console.log(1);
}
从该代码当中,不难看出。变量a
,必然不是一个字面量,比如数值或字符串,因为 a
不能同时等于多个值。。
具体的看一看,判断里面的a == 1 && a == 2 && a == 3
是一个短路逻辑与运算符,那表明左端条件为真的时候方可运行。
所以,a
的第一个值必然为1才能往下走,但是下一步a
的值有期望是2。由此可判断,a
的值或是间接返回值(类型转换后)应该是可以自增长的。
再看判断里面的==
运算,此类判断在JavaScript
里面:如果左右两边的类型是不同的,则会根据类型转换规则试图将它们转为同一类型再比较。
那么尝试定义变量a
为对象,因为使用了==
运算符(则尝试转换成Number
),则会调用a
的valueOf
和toString
方法来获得想要的基本类型,此处为Number
:
var a = {
value: 0,
valueOf() {
return ++this.value;
}
};
调取a
对象,因为==
运算,则获取valueOf
方法,获得1
;且是自增,下一次调用依然满足判断,依此类推,a == 1 && a == 2 && a == 3
为true
成立。
此处,使用:
var a = {
value: 0,
toString() {
return ++this.value;
}
};
也是可以的;
不过如果同时使用,
valueOf
的优先级会更高一点。
实现一个 sleep
函数,比如 sleep(1000)
意味着等待1000
毫秒
Promise
function sleep1(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, time);
})
}
sleep1(1000).then(() => console.log("sleep1"));
Generator
function* sleep2(time) {
return yield sleep1(time);
}
const s = sleep2(1500);
s.next().value.then(() => console.log("sleep2"));
Async/Await
async function sleep3(time) {
await sleep1(time);
}
(async () => {
await sleep3(2000);
console.log("sleep3")
})()
call
和 apply
的区别是什么,哪个性能更好一些
Function.prototype.apply
和Function.prototype.call
的作用是一样的,区别在于传入参数的不同;- 第一个参数都是指定函数体内
this
的指向; - 第二个参数开始不同,
apply
是传入带下标的集合,数组或者类数组,apply
把它传给函数作为参数,call
从第二个开始传入的参数是不固定的,都会传给函数作为参数; call
比apply
的性能要好,call
传入参数的格式正式内部所需要的格式;
为什么通常在发送数据埋点请求的时候使用的是 1x1
像素的透明 gif
图片?
- 能够完成整个
HTTP
请求+响应(尽管不需要响应内容); - 触发
GET
请求之后不需要获取和处理数据,服务器也不需要发送数据; - 跨域友好;
- 执行过程无阻塞;
- 相比
XMLHttpRequest
对象发送GET
请求,性能上更好; GIF
的最低合法体积最小(合法的GIF
只需要43
个字节)
实现 (5).add(3).minus(2) 功能
5加括号是因为数值后面的点,会被解释为小数点,而不是点运算符。
将数值放在圆括号中,数字就会自动转化为基本包装类型,就可以使用点运算符调用方法了。
Number.prototype.add = function(n) {
return this + n;
}
Number.prototype.minus = function(n) {
return this - n;
}
ES6
代码转成 ES5
代码的实现思路是什么?
Babel
的实现方式:
- 将代码字符串解析成抽象语法树,即所谓的
AST
; - 对
AST
进行处理,在这个阶段可以对ES6 AST
进行相应转换,即转换成ES5 AST
; - 根据处理后的
AST
再生成代码字符串;
js
中有哪几种内存泄露的情况
- 意外的全局变量;
- 闭包;
- 未被清空的定时器;
- 未被销毁的事件监听;
DOM
引用;
Q.E.D.