对一段js代码,js引擎并不是读一句执行一句,而是读取一段、解释执行一段。而一段一段执行,js会对读取的这段js代码整体有个预处理,这个预处理就是所谓的预解析。
声明和定义的区别
声明(declare):只是告诉浏览器这有一个变量,如:var name;function fn;
定义(defined):给我们声明的变量或函数赋值,如:name="xiaoming";fn=function(){}
变量只声明没有定义,默认值是undefined。
预解析阶段,js引擎会进行变量提升。
var和function在预解析阶段处理是不一样的
var,在预解析阶段只是提前声明了这个变量,只有当代码执行的时候才会赋值。
function,在预解析的时候会提前把声明和定义都完成了(在代码执行的时候遇到定义直接跳过)
ps:刚开始只对window下的进行预解析
console.log(obj);//->undefined
var obj = {name: "张珊珊", age: 10};
function fn(num1, num2) {//代码执行到这一行的时候直接的跳过,因为在预解释的时候我们已经完成了声明加定义
var total = num1 + num2;
console.log(total);
}
var num1 = 12;
fn(num1, 100);//执行fn,把全局变量num1的值赋值给形参num1,把100赋值给形参num2
fn函数中目前存储的都是字符串,所以var total没啥实际的意义,所以不进行预解释 -> "预解释是发生在当前作用域下的"
区别:带var 的可以在代码执行前进行声明,不带var的不能提前声明
预解析需要注意5点:
1.已经声明的变量不重复声明,只声明一次。
2.只对“=”左边的进行预解析,右边的是值不进行预解析。
3.if条件块中定义的函数,不管条件是否成立都会进行预解析。ps:不要在条件语句中定义函数,有兼容性问题。
4.函数体中return下面的代码都不在执行了,但是下面的代码需要参加预解释;而return后面的东西是需要处理的,但是由于它是当做一个值返回的,所以不进行预解释;
var total = 300;
function fn() {
console.log(total);
return function sum() {};//return是把函数中的值返回到函数的外面,这里是把function对应的内存地址返回的到函数的外面,例如:return xxxfff111;函数体中return下面的代码都不在执行了
var total = 10;
}
fn();
5.自执行函数不会进行预解析,执行的时候函数的声明+定义+调用同步完成
(function(num){console.log(num)})(100);
ps:在预解释的时候函数的优先级要比变量高
<script type="text/javascript">
var name = 'Jerry';
sayHi(name); // 输出 'Hi Jerry!'
var sayHi = function(name) {
alert('Hello ' + name + '!');
};
function sayHi(name) {
alert('Hi ' + name + '!');
}
sayHi(name); // 输出 'Hello Jerry!'
</script>
如上,因为JS的预编译,所以执行第一个sayHi(name);可以正常输出Hi Jerry!而不是sayHi未定义。而第二个sayHi(name); 执行时函数sayHi也被重新赋值,会输出Hello Jerry!。
<script type="text/javascript">
var name = 'Jerry';
sayHi(name); // 输出 'Hi Jerry!'
function sayHi(name) {
alert('Hi ' + name + '!');
}
</script>
<script type="text/javascript">
var name = 'Jerry';
sayHi(name); // 输出 'Hello Jerry!'
function sayHi(name) {
alert('Hello ' + name + '!');
}
</script>
```
因为JS的预编译,两个script标签分成2段代码分别读取解释执行,所以两个script标签内我们都可以得到预期的输出,而不是第二个sayHi覆盖了第一个sayHi。
```
var x = 1; // Initialize x
console.log(x + " " + y); //y is undefined
var y = 2;
//the above code and the below code are the same
var x = 1; // Initialize x
var y; // Declare y
console.log(x + " " + y); //y is undefined
y = 2; // Initialize y
```