JavaScript 预编译后的面试题
一、复习预编译
开始总结的那两条
1. 函数声明整体提升
2. 变量声明 提升
这两句话不用记了,是由预编译产生的环节。
由于预编译才产生了函数声明整体提升,由预编译才产生了变量 声明提升。
1、看一个问题
访问b输出的是什么值?
console.log(b); // undefined var b = function () { }
1. 访问b输出undefined,
2. 因为var b走的是变量,不是走函数。
预编译弄懂了之后,函数执行的任何顺序。一行一行怎么去执行,都没有任何问题了,预编译就是解决执行顺序问题的。
2、看第二题
下面的题有一个小bug:
if判断里面定义函数function c(){},大约在2016年之前谷歌浏览器内核浏览器是允许这么定义的,现在不允许了,但就当做它允许为了练题。
现在if判断里面定义一个函数声明,是语法不通过的,但是过去可以。
a = 100; function demo(e){ function e() {} arguments[0] = 2; console.log(e); if(a){ var b = 123; function c(){ // 过去谷歌浏览器内核是允许,if里面定义函数的,现在if里面定义函数声明是语法不通过的 } } var c; a = 10; var a; console.log(b); f = 123; console.log(c);// 这里应该打印function,现在打印的是undefined,因为现在if里不能定义函数 console.log(a); } var a; demo(1); console.log(a); console.log(f);
全局预编译:
第一步:生成GO{}对象
第二步:GO里面一个变量a,
GO{
a: undefined
}
第三步:然后还有一个函数声明
GO{
a: undefined,
demo: function(){code...}
}
GO完事了,开始执行
全局第一行:a = 100; 先把GO里面的a变成100
GO{
a: 100,
demo: function(){code...}
}
全局:然后demo函数忽略
变量a也忽略
直接demo(1)执行
全局:在 demo(1) 执行的基础上,函数预编译
第一步:创建AO{}
第二步:提升变量和形参
AO{
e : undefined,
b : undefined,
c : undefined,
a : undefined
}
第三步:实参形参相统一,实参e等于1
AO{
e: 1,
b: undefined,
c: undefined,
a: undefined
}
第四步:找函数声明,函数声明有function e(){}、function c(){}
AO{
e: function e(){},
b: undefined,
c: function c(){} if里面声明函数语法是不允许的,这里当做它可以,if里面的函数声明c在预编译环节正常提升
a: undefined
}
预编译完了,下面开始执行demo(1)函数里面的语句
05/
第一句:函数声明,不看了
第二句:arguments[0] = 2,
实参列表与传的参数位置相映射,你改我也改,我改你也改,
也就是arguments[0]与形参e相映射,相当于让形参e的值也变成2
AO{
e: 2,
b: undefined,
c: function c(){}, // 实际上c的值里是undefined
a: undefined
}
第三句:然后 console.log(e) 也输出 2
第四句:if(a) 此时a的值是undefined,a的值到AO里面找,不能通过判断if里面的语句不执行
第五句:var c; 不看
第六句:a = 10 a的值变成10
AO{
e : 2,
b : undefined,
c : function c(){}, // 实际上c的值里是undefined
a : 10
}
第七句: var a; 不看了
第八句:console.log(b); 再打印b输出AO里b的值是 undefined
第九句:f = 123; AO里没有f,扔给GO,f是暗示全局变量放到GO里面
GO{
a: 100,
demo: function(){code...},
f: 123
}
第十句:console.log(c); 打印c其实理想中是function但现是undefined,因为现在语法if里不允许声明函数
第十一句:console.log(a) AO里a的值是10,打印输出10
函数执行完事了,外部全局:
console.log(a) 全局上访问a,输出GO里a的值是 100
console.log(f) 全局上访问f,输出GO里的f值是 123
输出结果:2
undefined
undefined( IE老浏览器输入是function c(){} )
10
100
123
二、面试题
1、下面这些题处处是陷阱,考的全是隐式类型转换
第一题
加号两边只要没有"字符串",就是正常为数字相加,数字相加隐式转换类型成数字,false转化成数字是0,0加1等于1
var str = false + 1; document.write(str); // 1
第二题
这题这样解读,判断 false == 1 是否符相等,结果赋给demo。false不等于1,所以应该是false
var demo = false == 1; document.write(demo); // false
第三题
这道题是重点
if(typeof(a) && -true + (+undefined) + ""){ document.write("基础扎实"); }
1). 首先变量a未定义,typeof(a)不报错并输出字符串类型的"undefined",
只有typeof这一种情况,用未定义的变量是不报错,而且返回字符串类型的"undefined"
2). -true 转化结果是-1, +undefined 趋势是转为Number,但转不了转化值是NaN,
隐式类型转换最多的是数学符号,凡是数学符号的趋势一般是转换成数字,转不了的一般是NaN,但还是number类型。
3). -1 + NaN 还是NaN,NaN + ""(空字符串),结果是"NaN"的字符串
4). "undefined" || "NaN"
前面是字符串类型的"undefined",后面是字符串类型的"NaN",
"字符串类型"转化成布尔值都是true,所以并且判断一定能通过的。
5). 判断能通过,可以打印出 "基础扎实"
第四题
if(11 + "11" * 2 == 33){ document.write("基础扎实"); }
1). "11" * 2 不管乘法两边是什么,都要转化成数字的,字符串"11"转成成数字11,再乘2结果是数字类型的22,
2). 数字22在加11等于33
3). 33==33 打印基础扎实
类型转换除了加号以外,除、减、莫尔、乘等等都是把运算符两侧的东西转换成数字的。
比如:
document.write("11" - "2"); // 数字类型 9
第五题
这个题惊悚一点
!!" " + !!"" - !!false || document.write("你觉得能打印你就是猪");
首先知道一点"空字符串"和"空格字符串"不是一回事,
空格字符串转化是true
空串转化是false
document.write(Boolean("")); // false document.write(Boolean(" ")); // true
!!" " 非非空格字符串变成布尔值是true
!!"" 非非空字符串转换成布尔值是false
!!false 转换成布尔值是false
true + false - false 转换数字 1 + 0 - 0 = 1
1 || document.write("你觉得能打印你就是猪"); 前面是true就不往后看了,所以后面的不可能打印出来
如果你觉得能打印,你就是pork
2、写出下面程序的执行结果
var x = 1; if(function f() {}){ x += typeof(f); } console.log(x);
上面题没学到立即执行函数做不了,看下面这题
3、请写出window.foo的值(百度外卖的题)
这题是一个很简单的或运算符,但是或运算符暗藏杀机,但是这题考的挺缺心眼的
(window.foo || (window.foo = "bar"));
这题如果下面这样写,这道题就报错
(window.foo || window.foo = "bar");
首先清楚一点,这是一个优先级的问题,"或运算符"的优先级比赋值(等号)高
比如,下面a的值是2,"或"是运算符要先计算的
var a = 1 || 2;
所以要是这样写 ( window.foo || window.foo = "bar" ) 成了这两个window.foo || window.foo 两个先计算然后在赋值,是坚决不可以的,会报错Uncaught ReferenceError:……
所以这题出的很精准,在里面加了一个小括号 ( window.foo || ( window.foo = "bar" ) );
解题顺序:
1. 外面的括号,写不写没什么区别,反正先计算里面小括号里的
2. 先看里面括号(window.foo = "bar"),先把bar赋值给window.foo
3. 然后在看或运算符前面的window.foo的值是"bar",是"bar"就不往后读了
4. 最后是window.foo的结果是bar
这题缺心眼,就是往错了分析也能答对
先看window.foo是undefined,是undefined就往后看(window.foo = "bar")又变bar了,分析对分析错结果都是bar
但是正确的理解一定是先看(window.foo = "bar"),先把bar赋进去
4、记录几个笔试题
1、css中display的属性有几种,分别是什么?block、none、inline、linline_block……
2、css中list-style的属性有几种,分别是什么?
3、下面代码中,box_1和box_2平行排列均分父级的区域且没有边距,就是各占50%
<div class="box"> <div class="box_1"></div> <div class="box_2"></div> </div>
4、写出下面程序的执行结果
var b = function a(){ return 23; } typeof a();