众所周知,JavaScript是动态类型语言,比较灵活,常常存在一些令人的头疼的地方。
例如:
var a = 10 ;
add()
function add() {
return a + b;
};
var b = 1;
结果输出NaN ;
这就很令人头疼,下面我们来解释下为什么会出现这种情况吧。
1,JavaScript 语言类型
JavaScript是解释型语言,解释一行执行一行,也可以理解为读取一行执行一行(一行一行执行就对了)
2,预编译阶段
var
申明的变量会存在变量提升过程,函数也会存在这种情况 。提升可以分为全局变量,函数提升,和局部变量,函数提升(⚠️注意,变量提升优于函数提升!)
下面我们来看下题目执行顺序
首先预编译,
变量提升,
var a = undefind;
var b = undefind;
其次函数提升,
function add () {}
变量函数提升完之后开始计算机系统开始读取代码,第一行,解释一行。
首先执行第一行
var a = undefind ; => var a = 10; //解释第一行代码时发现变量被赋值
add(); //解释函数,去找函数
function add () { //执行函数内部函数
return a + b ; //此时 a = 10;b = undefind;
} //结束add()函数,Number ➕ undefind = NaN;
var b = undefind ; => var b = 1; //发现变量 b 被赋值
以上就是预编译和JavaScript代码执行顺序的顺序。
好了,下面我们来点面试题吧,相信大家也经常被这些面试题坑。
3,面试题start
3-1 : 简单使用
var one = 1 ;
var two = 2 ;
function sum () {
var three = 3 ;
two = two + three;
return one + three
};
var newSum = new Sum();
console.log(newSum);复制代码
相信大家看过前面的讲解就会立即可以想到结果, 没错答案是6 ;
我们来看下执行顺序吧。
//首先变量,函数提升
var one = undefind;
var two = undefind;
var newSum = undefind;
function sum() {};
//开始读取并解释JavaScript
var one = undefind => var one = 1;
var two = undefind => var two = 2;
function sum () {
// ⚠️ 函数内部也会存在变量和函数提升
var three = undefind; => var three = 3;
/*
two 被重新赋值,这里还有一个知识点,当函数
内部找不到变量,会向上一层找,一直找到window上,
如果找不到就是undefined,所以在函数内存查找two
找不到,会向上一层查找,在全局变量中找到two和one
*/
two = 2 => two = 2 + 3;
return one + two; //one = 1,two = 2, 输出3
}
//函数sum()的值为3,所以 newSum = 3 ;var newSum = undefind; => var newSum = new sum();
console.log(newSum); => console.log(3);
复制代码
3-2 : 进阶版本
var a = 1;
var b = 2;
function add () {
var c = 3;
return a + b;
}
var sum = new add();
console.log(sum);
console.log(c);复制代码
大家可以思考下会打印什么,先来过程吧
//预编译,变量,函数提升
var a = undefind;
var b = undefind;
var sum = undefind;
function add () {};
//读取解释代码
var a = undefind; => var a = 1;
var b = undefind; => var b = 2;
function add () {
var c = undefind; => var c = 3;
return a + b ; => 1 + 2;
}
var sum = undefind; => var sum = new add(); //var sum = 3;
console.log(sum) // 3
//这里涉及到一个新知识点,c属于局部变量,全局变量无法访问访问局部变量
//当然有一种方法可以访问,那就是闭包了?
console.log(c) // c is not defind;
复制代码
可能大家还是觉得很简单,那我们在加大难度。
3-3 : 稍高难度版本
var a = 1 ;
var b = 2;
var i = 0;
function add() {
for (;i < b ; i++) { (function (f) {
console.log(f)
})(i)
};
return a + i;
}
console.log(i);复制代码
这个算是难度加大版本的了,小伙伴们可以思考下,结果是什么
我们来看下过程
//预编译,变量函数提升 ⚠️ 预编译阶段仅仅只有函数和变量存在提升!
var a = undefind;
var b = undefind;
var i = undefind;
function add() {}
//读取解释JavaScript
var a = undefind; => var a = 1;
var b = undefind; => var b = 2;
var i = undefind; => var i = 0;
function add () {
//在函数内部无法找到 i 与 b 向上一层查找
for(;i < b ; i++) {
//立即执行函数,避免 i 提前变量赋值,
// 同样用let也可以避免这样的事情发生
(function(f){
// 立即执行函数和let形成暂时性死区效果一样,依次
//打印 0 => 1
console.log(f)
})(i)
//等等,你真的以为执行完了吗?i < b 当这个条件执行完,i被赋值为2,不要忘记这个小细节哦
}
}
console.log(i); // i 被重新赋值,打印2复制代码
所以结果依次为 0 ,1 ,2
当然还可以在难一点,可是楼主飞机误点了,一直在等飞机? 深圳这该死的 ☁️
有更好的面试题的小伙伴可以子啊下面留言告诉我呦,一同进步