前端一些题1
记录一些坑蒙拐骗的题,温故而知新。
var b = 3;
(function(){
b = 5;
var b = 2;
})()
console.log(b)
result
3
解析:就是一个闭包问题
如果改一下:
var b = 3;
(function(){
b = 5;
// var b = 2;
})()
console.log(b)
result
5
function getPersonInfo(one, two, three) {
console.log(one)
console.log(two)
console.log(three)
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
result
[ '', ' is ', ' years old' ] Lydia 21
解析:在函数内部,模板字面量会被解析成一个数组,其中包含了字符串部分和表达式部分的分割结果,有点像Array.split方法 getPersonInfoaaa ${person} is ${age} years old
会分割为
[ 'aaa ', ' is ', ' years old' ]
function getAge(...args){
console.log(typeof args)
}
getAge(21);
result
object
解析:结构以后args是[21]
let val = "0";
console.log('Value is '+(val != '0')?"define":"undefine");
val = "1";
console.log('Value is '+(val != '0')?"define":"undefine");
result
define define
解析:三元运算符地位比较低,所以这题实际上是 "Value is true"?"define":"undefine"
console.log(1 + "2" + "2");
console.log(1 + +"2" + "2");
console.log("A" - "B" + "2");
console.log("A" - "B" + 2);
result
122 32 NaN2 NaN
解析:
第一个,当字符串做加法的时候,其他类型都会转字符串;
第二个,+"2"会把字符串的2转变为数字2,所以就变成了1+2+"2";
第三个,"A" - "B"会尝试把减号前后转换为数字,但是转不动所以变成了NaN,再加"2"
第四个,NaN + 2 = NaN
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
result
10个10
解析:应该有人答10个9,总之就是一个闭包问题,要解决这个问题很简单:
for (let i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
或者
for (var i = 0; i < 10; i++) {
(function (i){
setTimeout(function () {
console.log(i);
}, 0);
})(i)
}
改改:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
i = 20;
result
10个20
解析:event loop,没什么好说的
console.log(["1", "2", "3"].map(Number.parseInt))
result
[ 1, NaN, NaN ]
解析:实际上这里是:
console.log(["1", "2", "3"].map((v,i) => Number.parseInt(v,i)))
// 相当于执行了 Number.parseInt("1",0) 10进制
// 相当于执行了 Number.parseInt("2",1) 1进制
// 相当于执行了 Number.parseInt("3",2) 2进制
具体来说,parseInt 的行为如下:
- 如果第二个参数未指定,则默认为 10(十进制)。
- 如果第二个参数为 0 或未指定,则根据字符串的开头来确定进制:
- 如果字符串以 "0x" 或 "0X" 开头,则使用十六进制。
- 如果字符串以 "0" 开头,则使用八进制。
- 其他情况下,默认为十进制。
- 实现给定一个数进行加或减,例如给定一个数字7进行减1加2操作,比如: (7).minus(1).add(2)
result
原型上面定义方法,没啥好说的
Number.prototype.minus = function (num) {
return this - num
};
Number.prototype.add = function (num) {
return this + num
};
console.log((7).minus(1).add(2));
- 当a等于什么的时候使得下面可以输出console.log
var a = ??;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
result
类似vue双向绑定的写法
let value = 0;
Object.defineProperty(globalThis, 'a', {
get() {
return ++value;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
改改题目:
var a = ??;
if (a == 3 && a == 1 && a == 2) {
console.log(1);
}
result
let value = 0;
Object.defineProperty(globalThis, 'a', {
get() {
return [3, 1, 2][value++];
}
});
if (a == 3 && a == 1 && a == 2) {
console.log(1);
}
- 输出是什么
async function m1() {
return 1;
}
async function m2() {
const n = await m1();
console.log(n)
return 2;
}
async function m3() {
const n = m2();
console.log(n);
return 3;
}
m3().then(n => {
console.log(n);
})
m3();
console.log(4);
result
// Promise { <pending> }
// Promise { <pending> }
// 4
// 1
// 3
// 1
如果你错了,没关系,因为刚开始我也错了,那么开始剖析:
async function m1() {
return 1;
}
async function m2() {
const n = await m1();
console.log("m2")
console.log(n)
return 2;
}
async function m3() {
const n = m2();
console.log("m3")
console.log(n);
return 3;
}
m3().then(n => {
console.log("then")
console.log(n);
})
m3();
console.log(4);
---------分割线---------
// m3 Promise { <pending> }
// m3 Promise { <pending> }
// 4
// m2 1
// then 3
// m2 1
分析:
首先16行代码执行,然后走到11行,再走到5行,此时await存入微任务,然后回到12行输出,同时17行也进入微任务;
执行20行代码,然后走到11行,再走到5行,此时await存入微任务,然后回到12行输出,此时微任务里面存在三个(6行 17行 6行);
21行输出没什么好说的;
剩下的就是微任务执行,也没什么好说的,注意17行输出的是3;
console.log(1)
const promise = new Promise((resolve, reject) => {
console.log(2);
setTimeout(() => {
resolve(3);
reject(4);
}, 0);
});
promise.then((data) => {
console.log(data);
}).catch((error) => {
console.log(error);
});
console.log(5);
result
1 2 5 3
- 输出1没什么好说的
- promise在定义的时候要执行callback,不懂就去看promise源码,输出2
- setTimeout进宏任务队列
- then进微任务队列
- 输出5
- 输出3
- promise执行完成不会再走catch了
- 上文中
resolve(3)
和reject(4)
互换一下就会变成1 2 5 4
,没什么好说的了
var fullname = 'a';
var obj = {
fullname: 'b',
prop: {
fullname: 'c',
getFullname: () => {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());
result
// a a
题目很简单,但是这里有一个问题,如果这个代码在node运行的话,有几点要注意:
- node中定义
var fullname
不会挂到global
上面 - 这里的
this
指向exports
或者module.exports
getFullname: () => {return this.fullname;}
改为getFullname: function(){return this.fullname;}
的时候this
才是global- 同理,在3的基础上继续修改第一行改为
this.fullname = 'a'
也是没用的,改成global.fullname = 'a'
才可以得到c a
的结果
后记
老板,续一杯 卡布奇诺