JavaScritpt解析和执行过程介绍

javascipt是一种描述型的脚本语言,是一种解析语言,由浏览器动态解析,不同种类浏览器不同版本的浏览器对js的解析有着微小的差别,不同浏览器js解析引擎效率也有高低。
js的执行过程分为两大部分:
第一部分,解析过程,也称预编译期。主要工作就是对js代码中声明的所有变量进行预处理。需要注意的是,在此进行处理的仅是声明函数,而对于变量的处理仅是声明,并开辟出一块内存空间,不进行赋值操作。
第二部分,执行过程,在执行过程中,浏览器的js引擎对每块代码进行顺序执行,如果有外部引用的js,且js有相互关联,此时就要注意,不同的js的引入顺序,如果声明代码块在调用代码块后调用则将不会达到预期效果。
总的来说,js的执行分为两部分,解析过程和执行过程。解析时按照代码代码块,一段一段进行解析,执行时按照代码块顺序逐行执行,解析一个代码块执行一个代码块。
因为是解释性语言,所以js如果在解析过程中有错误,则不会提示,也可以理解为js不会出现编译错误,但如果出现了运行时错误。

var ad;//预处理阶段处理
 ad = 1;//运行时赋值
 function text(){
	console.log(1);
 if(ad){//boolea
 }
}

为什么变量是在运行时赋值的而不是在预处理阶段进行赋值?

因为javascript的变量的数据类型不是固定的,要根据当前运行的情况的判定。

全局预处理阶段

预处理:创建一个词法环境(LexicalEnvironment,在后面简写成LE),扫描JS中的用声明的方式声明函数,用var定义的变量并将他们加到预处理阶段中的词法环境中去。
预处理阶段先读取代码块,不是一行一行的解析执行定义的方法和var定义的变量,会放到一个(不同的环境,会有对应语法的环境)词法环境中

var a = 1;
var b;
c = 3;
function d(){
console.log('hello');
}
var e = function(){
 console.log('world');
 }

词法环境:

LE{//此时的LE相当于window
	a:undefined
	b:undefined
	没有c
	d:对一个函数的引用
	e:undefined
}

预处理的函数必须是JS用声明的方式声明函数(不是函数表达式)
示例:

d();
e();
function d(){//用声明的方式声明函数
	console.log('hello');
}
var e = function(){//函数表达式
	console.log('world');
}

词法环境:

LE{//此时的LE相当于window
	d:对函数的一个引用
	e:undefined
}

结果:hello;报错e is not a function

命名冲突

变量和函数同名冲突–函数优先,函数是一等公民,在既有函数声明又有变量声明的时候,函数声明的权重总是高一些,所以最终结果往往是指向函数声明的引用。

function f(){console.log(2);}
var f = 1;
console.log(f);

console.log(f)结果是2

function fa(){
var f = 3;
console.log(2);
}
var f = 1;
console.log(f);

console.log(f)结果是1

执行阶段
console.log(a);
console.log(b);
console.log(c);
console.log(d);
var a = 1;
b = 2;
console.log(b);
function c(){
	console.log('c');
}
var d = function(){
 console.log('d')
}
console.log(d)
LE{
	a:undifined
	没有b
	c:对函数的一个引用
	d:undefine
}

结果:

undefined
报错
function c(){console.log('c');}
undefined

注释上面代码第二行
1.在第6行代码执行完,LE中的a值变为1;

LE{
	a:1
	没有b
	c:对函数的一个引用
	d:undefine
}

2.第7行代码执行完,LE中就有了b的值(且b的值为2,此时b的值直接变为全局变量)

LE{
	a:1
	b:2
	c:对函数的一个引用
	d:undefine
}

3.第10行代码执行完

LE{
	a:1
	b:2
	c:指向函数
	d:undefine
}

3.第14行代码执行完

LE{
	a:1
	b:2
	c:指向函数
	d:指向函数
}
函数冲突原则

1.处理函数声明有冲突时,会覆盖。
2.处理变量声明有冲突,会忽略。以传入参数的值为准。
预处理阶段传入参数值一 一对应

function f(a,b){
	alert(a);
	alert(b);
	
	var b = 100;
	function a(){}
f(1,2);
}
LE{
   b:2
   a:指向函数的引用
   arguments:2
   //arguments调用函数时实际调用的参数个数
}

js程序bug:函数内没有使用var声明的变量是全局变量。