1. js执行过程
按html文档流的顺序执行js代码
1. 声明阶段:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,函数则是在预定义阶段直接定义和赋值
2. 解释执行阶段:遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = …这样的语句时会给相应的变量进行赋值,在这个阶段前使用变量的话会是undefined
-
举例1
console.log(a)//undefined var a = 1; console.log(a)//1
- 声明在前赋值在后,执行代码前已经被声明未赋值,默认为undefined,所以第一个打印结果为undefined,第二个打印在赋值之后,所以结果为赋值后的值为1
-
举例2
f1()//报错 f1不是一个方法 f2()//2 var f1 = function () { console.log(1) } function f2() { console.log(2) }
- f1在声明为一个变量,f2则为函数,变量先声明再赋值,调用在赋值前面,因此f1()等价于undefined()因此报错。f2为函数,优先级高,在一开始就被赋值,所以可以注册执行并且打印结果为2*
-
举例3
var sum = function(){}//第一个sum alert(sum(10,11));//22 function sum(a,b){//第二个sum return a+b+1; } alert(sum(10,11));//22 var sum = function(a,b){//第三个sum return a+b; }
- 函数声明优先级高于变量:第二个sum大于第一与第三,所以只看第二个即可,第一个alert调用第二个sum,第二个alert也调用第二个sum,因此结果相等
-
举例4
(function fn(){ nn = 123 })() console.log(nn)
- 没有var、let、const等声明,默认全局变量,在函数体外都可以访问
-
举例5
{ var i = 9; } console.log(i); // 9
- 在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围
-
举例6
{ let i = 9; // i变量只在 花括号内有效!!! } console.log(i); // Uncaught ReferenceError: i is not defined
- ES6新增的let,可以声明块级作用域的变量。
-
举例7
console.log(text); // 报错:Uncaught ReferenceError let text = "hello word"; console.log(text) // hello word
- let 声明语句必须执行完才能使用,否则报错
-
举例8
let a = 1; let a = 3;// Uncaught SyntaxError: Identifier 'a' has already been declared
var a = 1; var a = 3; console.log(a)//3
var a = 1; let a = 3;// Uncaught SyntaxError: Identifier 'a' has already been declared
let a = 1; var a = 3;// Uncaught SyntaxError: Identifier 'a' has already been declared
- var可以重复声明、let不可以,只要存在是被let声明的变量名称,之后只能赋值不能被任何方式重复声明