js是一门解释型语言,解释一句执行一句
- js执行的过程
- 通篇语法扫描检查错误
- 预编译:
- 代码执行顺序,逐行执行
1. 通篇语法扫描检查错误:不管写多少行代码,代码执行前js都会进行语法检查错误
// 通篇语法扫描检查错误
console.log("1");
console.log(a);//这里报错下面就不执行了
console.log("3");
全局预编译
- 创建以个函数的GO对象(执行期上下文对象)(Global Object)
- 将var声明的变量成为AO对象的属性,值为undefined,遇到重名不做变化,不覆盖
- 将function声明的函数成为AO对象的属性,值为函数执行代码,重名直接覆盖
- 全局预编译与函数预编译是差不多的,一个是script标签执行前创造一个GO对象,将script里面声明的变量和函数成为AO的属性,一个是函数执行前创建AO
var a = 1;
var b = 2;
function a(){
var c = 3
}
a()
// 全局预编译
GO{
AO{
// 第一次A属性
a : undefined
// 第一次B属性
b : undefined
// 第二次A属性是函数直接覆盖上一次A属性
a : function
// A函数执行前又生成一个AO属性为C
AO{
// 第一次C
c : undefined
}
}
}
预编译
- 什么是预编译,执行期上下文叫预编译
解释:就是在一个函数运行之前在内存里面创建一个空间,为此函数要执行的数据提供支持
—变量声明提升 —函数声明提升:变量声明就是在声明一个变量后会提升到顶端、函数声明一个函数后也会提升到顶端
this
ao
aarguments[0]
- 函数预编译:
- 上面讲到了从一个函数运行之前会预编译 创建一个AO(执行期上下文)(Activation Object)
- 函数的形参成为AO(Activation Object)对象的一个属性,值为传入的实参,如果未传参,则值为udefined
- 将var声明的变量,也是成为AO(Activation Object)的对象属性,值为udefined,遇到重名的不做任何变化:不覆盖不成为属性
- 将function声明的函数,一样成为AO(Activation Object)对象的属性,值为要执行的函数体,遇到重名直接覆盖前面的,跟var声明不同
- 执行b()函数执行函数,打印a因为刚刚a声明提升至函数顶端是,a :undefined为什么不是1, ,因为js是逐行执行还为到给a赋值1的一行,都将var声明提升了所以undfined
function b(){
console.log(a);
var a=1;
}
b()
// 预编译开始
// 创建AO{
// 第一次a为undefined
// a :undefined
// 预编译完
// 第二次赋值a为1
// }
- 函数的形参成为AO(Activation Object)对象的一个属性,值为传入的实参,如果未传参,则值为udefined,都将var声明提升了所以undfined
:未传入参数undefined
function b(num){
console.log(num+"1");
}
b()
//预编译开始
//创建AO{
// 属性
// num:undefined
// }
// 未传入参数undefined
-将function声明的函数,一样成为AO(Activation Object)对象的属性,值为要执行的函数体,遇到重名直接覆盖前面的,跟var声明不同
function b(){
console.log(a);
var a=123;
function a(){
}
}
b()
// 预编译开始
// 创建AO{
// a:undefined
// a:function//覆盖上面a:undefined
//打印a函数
// }
- 将var声明的变量,也是成为AO(Activation Object)的对象属性,值为udefined,遇到重名的不做任何变化:不覆盖不成为属性
—因为预编译是看不见的也没法证明第二a没有覆盖前一个:只有执行了第一次a赋值为1第二次赋值为2才会覆盖
function b(){
var a =1;
var a =2;
}
b()
// 预编译开始
// 创建AO{
// 属性
//第一个a为
// a : undefined
// 第二a重名了
// a : undefined 不做任何变化不覆盖
// }
预编译前奏
- imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值。此变量就归全局所有(window)
- 所有声明的全局变量,都是(window)属性
-
大家都知道函数里面声明的变量外部不可用,但是在函数内部未经声明就赋值的变量,就归全局所有(window),此时全局就可以调用
-
此时可以在函数外部调用吗?肯定是可以,因为未经声明就赋值此变量归全局
function a(){
b = 1 ;
c = 1;
}
a()
console.log(b,c);
作用域
- 作用域就是变量和函数可以访问的区域
两种作用域
- 全局作用域
- 写在script标签中的代码,全局作用域中的变量声明会被提升到script标签顶部进行定义。成为全局对象的属性(window)
- 局部作用域可以说是函数的作用域
- 在script标签里面声明一个函数,这个函数的{}括号里面就是一个局部的作用域,里面声明的变量会被提升到函数作用域顶部进行定义,不会成为全局对象的属性(window)
- 变量污染
- 函数中声明的变量不会造成全局变量的污染,请把每一个功能封装成为一个函数,因为全局变量谁都可以调用
var a = 0;
var b = 1;
var c = 2;
// 写在script里面不是函数里面的是全局作用域
function d(){
var x= 1;
var y=2;
var z=3;
// 这是d函数里面的一个局部作用域不能被外部使用除非return这是闭包的用法
}
作用域链
- 万物皆对象:函数也是对象,有的对象属性我们可以访问到比如name,但是有些属性是我们访问不到的,只有JS引擎进行读取
- [[scope]]就是只有JS引擎可以读取的函数属性是:所有的执行期上下文的集合,把所有的GO、AO集合起来
- 执行期上下文对象,是当一个函数执行时,创建一个支持改函数数据,每一个都是独一无二,如果再执行 一次此函数虽然数据是一样的,但是是独一无二的,执行一次创建一次,执行完立即销毁