JavaScript预解析

对一段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

```

推荐阅读更多精彩内容

  • js是运行在浏览器端的,浏览器内部众多功能中有一个小功能叫做js解析器。js在解析器在运行js代码时分为下面两步:...
    帅气的刘小二阅读 46评论 0 0
  • JavaScript是解释型语言是毋庸置疑的,那么它是不是仅在运行时自上往下一句一句地解析的呢? 事实上或某种...
    SandyFrankie阅读 77评论 0 0
  • 概念:函数或者变量都会有一个提前解析的过程,js会把函数或者变量提前解析一下、解析到它们对应的作用域最开始的位置 ...
    wn_Smile阅读 30评论 0 0
  • 在ES6之前,变量使用var声明,会存在变量的预解析(函数也有预解析),我相信很多同学在刚开始学JavaScrip...
    iceman_dev阅读 3,295评论 5 33
  • 翡翠又名翠玉,是在地质作用下形成的达到玉石级的石质多晶集合体。
    百世爱掌柜阅读 33评论 0 0