JS的两大特点
1,单线程语言,什么是单线程,就是说JS同一时间只能做一件事,即使是HTML5中提出JS可以创建多个线程,但是还是要受主线程控制,并且不能操作DOM。所以本质上来说,JS还是单线程语言。
2,解释性语言,即翻译一句执行一句,但又不是真的这么直接。
console.log(a) // undefined
console.log(b) // 报错
var a = 10;
我们发现a是undefined而b直接报错,从这里我们可以看到JS不是单纯意义上的翻译一句执行一句,要不然a应该会直接报错,下面的不执行。其实JS执行分三步。
1,语法分析 通篇扫描看看有没有低级错误(少写大括号,中文标点什么的)。
2,预编译
3,解释执行 解释一行执行一行。
现在我们要理解的就是其中的预编译环节,要了解预编译首先要知道一个词global (全局变量)。
1,一切未经声明的赋值,就为全局对象(window)所有。
function text(){
b = 10;
}
text();
console.log(window.b) // 10
2,在全局范围声明的全局变量都是全局属性。
var a = 12;
console.log(window.a) // 12
好了先看一下预编译的步骤预编译分为函数预编译和全局预编译,咱们先看一下函数的,然后全局预编译就简简单单了。
函数预编译四部曲:
- 创建AO对象 Activation Object;(执行期上下文) ;
- 找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined ;
- 将实参值和形参统一;
- 在函数体里找函数声明,值为其函数体。
直接写出来看的不是很明白,可以通过JS题来验证
function fn(a){
console.log(a);
var a = 123;
console.log(a);
function a(){};
console.log(a)
console.log(b)
var b = function (){}
console.log(b);
function d(){}
}
fn(1);
看到这道题先别慌,按照步骤一步一步来。
1,创建AO对象 Activation Object (执行期上下文)
AO{ }
2,找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined ;
从上往下的找形参和变量声明,为他们赋值undefined,遇到同名的下面的覆盖上面的。
AO{
a : undefined,
b : undefined,
d : undefined
}
- 将实参值和形参统一; 发现a的实参是1
AO{
a : 1,
b : undefined,
d : undefined
}
- 在函数体里找函数声明,值为其函数体。a和d是函数声明,为他们赋值函数体,b是函数表达式,所以不进行这一步。
AO{
a : function a(){},
b : undefined,
d : function d(){}
}
这下就是预编译完成了,预编译在函数执行的前一刻,所以预编译刚完成,函数就开始执行。
function fn(a){
console.log(a); //function a (){} 打印a函数上哪找a在自己的AO对象了,发现a是函数体,于是打印函数体
var a = 123;
console.log(a); // 123 这里预编译看的是有一个b变量后面的没看,所以看到后面的123,就为a赋值123
function a(){}
console.log(a); // 123 这里因为预编译已经看过这a函数了,所以执行的时候就不会再看了
console.log(b) ; // undefined 这里看AO里有b就打印undefined
var b = function (){}
console.log(b); // function(){} 这里预编译看的是有一个b变量后面的没看,所以执行的时候看到后面的函数体,为b赋值函数体。
function d(){}
}
fn(1)
好了基本函数的预编译这样就差不多了,还有一个就是函数在自己AO对象找不到变量的时候,会在全局对象GO即window中找,都找不到就会报错。
全局预编译三部曲
- 创建GO对象:执行期上下文(Global Object) GO === window
- 寻找变量声明,并且当做属性放在GO对象里,值为undefined
- 寻找函数声明,值赋予函数体
console.log(a) // undefined 在全局GO{a;undefined,text:function text () {} }早到a 打印undefined
function text(){}
console.log(b) // 报错
var a = 10;
全局的预编译和函数一样,由于没有参数,还显得更为简单,我就不多赘述了。
然后这个主要是多记多做题,就可以熟练地掌握了。我这里这写几道题,大家可以自己看看。
function test(a, b) {
console.log(a);
console.log(b);
var b = 234;
console.log(b);
a = 123;
console.log(a);
function a() { }
var a;
b = 234;
var b = function () { }
console.log(a);
console.log(b);
}
text(1)
console.log(test);
function test() {
console.log(test);
var test = 234;
console.log(test);
function test() { }
}
test(1)
global = 100;
function fn() {
console.log(global);
global = 200;
console.log(global);
var global = 300;
}
fn();
入职不久的小前端从今以后开始自己的技术分享之旅,欢迎建议和批评。