1、当浏览器加载HTML页面时候,首先会提供一个供全局JS代码执行的环境:全局作用域(globa/window)
2、预解释(也就是变量提声):在当前作用域下,JS代码执行之前,浏览器首先会默认把所有带var和function的进行提前声明或者定义
(1)理解声明和定义
var num = 12;
声明(declare): var num; -> 告诉浏览器在全局作用域中有一个num的变量
定义(defined):num=12;->给num变量进行赋值
(2)对于带var和function关键字在预解释时候操作不一样
var -> 在预解释时候只是提前声明
function -> 在预解释时候提前声明,同时完成了定义
(3)预解释只发生在当前作用域下,例如:开始只对window下进行预解释,只有函数执行的时候才会对函数中的进行预解释。
(4)预解释的时候不管条件是否成立,都要把带var进行提前的声明
//预解释:var num; --> window.num
if(!("num" in window)) {
var num = 10;
}
console.log(num); //undefined
(5)预解释只解释“=”左边的,不解释右边的值
//预解释:var fun;
var fun = function foo() {
console.log('ok');
}
(6)自执行函数:在全局作用域下不进行预解释,当代码执行到这个位置的时候定义和执行一起完成。
//括号、~、+、-、!都是一样的,没什么区别,都是为了自执行函数能正常编译和执行
(function(num){})(100);
(function (num) {}(100));
~function (num) {}(100);
+function (num) {}(100);
-function (num) {}(100);
!function (num) {}(100);
(7)函数体中return下面的代码虽然不再执行,但是需要进行预解释;return后面跟着都是返回值,所以不进行预解释
function fun() {
//预解释:var num;
console.log(num); // -->undefined
return function () {
console.log('ok');
};
var num;
}
(8)预解释时候,如果名字已经声明过了,不需要重新声明,但是需要重新的赋值。
在JS中,如果变量的名字和函数的名字重复了,也算冲突。
//预解释过程:
//声明+定义 fn=xxxfff111
//声明 var fn; (不需要重新声明)
//声明(不重复进行)+定义 fn=xxxfff222
//-->fn=xxxfff222
fn(); //->2
function fn(){console.log(1)};
fn(); //->2
var fn = 10; //->fn=10
fn(); //->10() Uncaught TypeError: fn is not a function
function fn(){console.log(2)};
fn(); //前面报错了,就不执行了