1. 序言
对于一个web后端来说,笔试的时候难免会遇到javascript笔试题。 就我而言。 笔试题有好几道,有的是我在笔试中遇到的,有的是我在网上看到的,都让人印象深刻。 明天我就简单分析一下我遇到的一些印象深刻的笔试题! 主要目的是让男伴学到一些东西。 如果以后遇到类似的情况,切记不要落入陷阱!
2. 预分析
预解析:当前作用域内,js运行前,会预先声明关键字var和function,但不带形参(个人意见)
预分析给我留下了深刻的印象,不是因为难,而是要细心,大惊小怪,答案就会错! 我遇到的预分析题目不止一个,现在能记住的有两个,我告诉你吧!
2-1. 预解析1
alert(a)
a();
var a=3;
function a(){
alert(10)
}
alert(a)
a=6;
a();
------------分割线------------------
alert(a)
a();
var a=3;
var a=function(){
alert(10)
}
alert(a)
a=6;
a();
当我看到这段代码时,我错了。 后来向同学请教,自己理解后,就理顺了! 虽然只有两个测试点,但是第一个变量声明更早,第二个函数声明优先于变量声明! 我简单分析一下第一部分的运行结果: 1、函数声明优先于变量声明,所以一开始a是functiona(){alert(10)},你会听到这个函数。 2. a(),执行函数,即出现alert(10) 3. 执行vara=3; 所以alert(a)显示34。因为a不再是一个函数,所以当执行到a()后,报错。 第二部分运行结果: 1. underfind 2. 报错前面说过,预解析就是预先声明带var和function的关键字,但不带形参。 所以一开始是underfind,然后就报错了,因为执行a()的时候,a不是一个函数。
//函数表达式,和变量声明同等
var a=function(){
alert(10)
}
//函数声明,优于变量声明
function a(){
alert(10)
}
2-2. 准备工作和范围
var a=0;
function aa(){
alert(a)
a=3
}
//结果是什么都没发生,因为要执行aa函数才会执行alert(0)
------------分割线1------------------
var a=0;
function aa(){
alert(a)
var a=3
}
aa();
//underfind 在aa函数里面,有var a=3,那么在aa作用域里面,就是把a这个变量声明提前,但是不会赋值,所以是underfind
------------分割线2------------------
var a=0;
function aa(a){
alert(a)
var a=3
}
aa(5)
alert(a)
//5,0 在函数体内,参数a的优先级高于变量a
------------分割线3------------------
var a=0;
function aa(a){
alert(a)
a=3
}
aa(5)
alert(a)
//5,0 在函数体内,执行alert(a)和a=3,修改的的并不是全局变量a,而是参数a
------------分割线4------------------
var a=0;
function aa(a){
alert(a)
var a=3
alert(a)
}
aa(5)
//5,3
//这个我也有点不理解,请教网上的说法,有两个答案(小伙伴如果知道怎么理解,欢迎在评论上指点)
//1.参数优先级高于变量声明,所以 变量n的声明其实被忽略了,此时相当于
//var a=0;
//function aa(a){
// var a=5;
// alert(a)
// a=3
// alert(a)
//}
//aa(5)
//2.形参和局部变量优先级一样,此时相当于
//var a=0;
//function aa(a){
// var a; 先声明
// a=5 由于形参和变量名称一样,覆盖了!
// alert(a)
// a=3
// alert(a)
//}
//aa(5)
------------分割线5------------------
var a=0;
function aa(a){
alert(a)
a=3
alert(a)
}
aa()
alert(a)
//underfind 3 0
//首先,参数优先级高于全局变量,由于没传参数,所以是underfind
//a=3,实际上修改的时形参a的值,并不是全局变量a,往下alert(a)也是形参a
//最后的alert(a),你懂的
3. 递归3-1。 斐波那契域
这个就不多说了javascript for 作用域,简单又经典。就是当前项等于前两项之和
var arr=[];
for(var i=0;i<10;i++ ){
i<=1?arr.push(1):arr.push(arr[i-1]+arr[i-2]);
}
console.log(arr)
3-2. 资料整理
比如12345432123456765432怎么办?当时我的方法是分两步写的,先显示上面的,然后显示前面的代码是
//01234543210
//先展示前面的 01234
//n:开始的数字 m:结束的数字
function num1(n,m){
for(var i=n;i<m;i++){
//再展示后面的 543210
console.log(i);
if(i===m-1){
num2(n,m)
}
}
}
function num2(n,m){
for(var i=m;i>=n;i--){
console.log(i)
}
}
test(2,5) //2345432
这种方式代码太多了,后来研究了一下这些
function num(n,m){
console.log(n);
if(n<m){
test(n+1,m);
console.log(n);
}
}
num(2,5) //2345432
解释如下 1.首先执行num(2,5),即
console.log(2); -> test(3,5); -> console.log(2);
//执行test(3,5); 就是是相当于 console.log(3); -> test(4,5); -> console.log(3); 下面以此类推
console.log(2); -> console.log(3); -> test(4,5); -> console.log(3); -> console.log(2);
然后就是
console.log(2); -> console.log(3); -> console.log(4); -> test(5,5); -> console.log(4); -> console.log(3); -> console.log(2);
最后就是
console.log(2); -> console.log(3); -> console.log(4); -> console.log(5); -> console.log(4); -> console.log(3); -> console.log(2);
4.其他4-1
function foo1()
{
return {
bar: "hello"
};
}
function foo2()
{
return
{
bar: "hello"
};
}
var a=foo1();
var b=foo2();
console.log(a) //Object {bar: "hello"}
console.log(b) //underfind
//仔细看就知道了
4-2###
针对网上听到的题目javascript for 作用域,我修改了80%应聘者不及格的JS笔试题()
for (var i = 0; i < 5; i++) {
console.log(i);
}
console.log(i);
//这个大家应该很快就知道了,012345
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
console.log(i);
//这个大家就要小心一点了,答案是5 55555
//在setTimeout执行之前,for循环早就执行完了,i的值早已经是5了,所以一开始是执行,最后面的console.log(i);
//在for循环的时候一下子自定义5个setTimeout,大概一秒后,就是输出55555
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
console.log(i);
//这里的解析和上面基本一样,只是用闭包来记录每一次循环的i,
//所以答案是5 01234
var output = function (i) {
setTimeout(function() {
console.log(i);
}, 1000);
};
for (var i = 0; i < 5; i++) {
output(i); // 这里传过去的 i 值被复制了
}
console.log(i);
//这里的解析和上面基本一样,把i当参数传进output,记录每一次循环的i,
//所以答案是5 01234
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
console.log(i);
//结果是 报错 01234
//注意i是用let定义的,不是var
5. 总结
首先我想说这是我遇到过的一些话题,印象比较深刻的一些话题不一定是常见的话题。 之后这篇文章可以说是我的一个笔记,记录了我遇到的问题。 给男同伴发这样的笔试文章的目的并不是为了让男同伴背题目和答案,或者为了应付笔试。 这是没有意义的,也是不现实的! 我的目的就是让大家学习,通过提问知道一些原理和运行机制,或者知道一些可能的“陷阱”。 另外,我还遇到过很多实际操作问题,比如链表去重、扰乱链表、统计链表每个元素出现的次数、字符串每个字符出现的次数、获取每个地址链接的参数等。 这类题不仅在笔试题中出现较多,在实际项目开发中也经常使用,男伙伴可以自行学习。 其实我自己也封装了一些函数,就是实现上面提到的操作的函数。 近期我也会写一篇关于这方面的文章,记录一下我封装了哪些功能,以及封装了哪些常用的功能。 稍后我会分享。 如果有需要修改的地方,或者好的建议,请强调!
尖端
长按二维码加入SF“2017华为开发者大赛交流群”了解更多详情,与男同伴组队。