先看看一个简单的代码
var str='Hello World'; alert(str);//弹出 Hello World
再看一段代码:
var v='Hello World'; (function(){ alert(v); })() //和我们预期的一样,还是弹出 Hello World
那么铺垫完了,继续coding
var str='Hello World'; (function(){ alert(str); var str='I love coding...'; })() //出乎我们的意料,弹出 undefined
继续…
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar();// 10
再来:
var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a); //1
1.变量提升
就是把变量提升提到函数的top的地方。同时需要注意的是变量提升只是提升变量的声明,并不会把赋值也提升上来。比如:
(function(){ var a='One'; var b='Two'; var c='Three'; })()
实际上它是这样子的:
(function(){ var a,b,c; a='One'; b='Two'; c='Three'; })()
那么现在我们分析下刚才出现很尴尬的结果
var str='Hello World'; (function(){ alert(str); var str='I love coding...'; })()
其实,根据我么根据上面变量提升原件以及js的作用域(块级作用域)的分析,得知 上面代码真正变成如下:
var str='Hello World'; (function(){ var str; alert(str); str='I love coding...'; })()
所以,才会提示说 undefined
这里,我们应该受到启发:我们在写js code 的时候,我们需要把变量放在函数级作用域的顶端,比如我在上面所举的例子:var a,b,c;。以防止出现意外。
2.函数提升
函数提升是把整个函数都提到前面去。在我们写js code 的时候,我们有两种写法,一种是函数表达式,另外一种是函数声明方式。我们需要重点注意的是,只有函数声明形式才能被提升。例子说明:
function getName() {console.log(5)}; var getName = function() {console.log(4)}; getName()
var getName = function() {console.log(4)}; function getName() {console.log(5)}; getName()
执行上面的两块代码,会发现 打印的都是 4 而不是 5
//函数声明方式提升【成功】 function myTest(){ foo(); function foo(){ alert("我来自 foo"); } } myTest();// 我来自 foo //函数表达式方式提升【失败】 function myTest(){ foo(); var foo =function(){ alert("我来自 foo"); } } myTest();//Uncaught TypeError: foo is not a function
3.作用域链
3.1变量必须先声明后使用,函数可以先使用、后声明
原因是:函数有预加载的过程(函数声明先于其他执行代码进入内存)。本质还是函数的声明在前,使用在后。
console.log(subject);//undefined var subject="javascript"; //var命令会发生”变量提升“现象, //即变量可以在声明之前使用,值为undefined //函数可以先使用、后声明 f1();//I am f1 function function f1(){ console.log("I am f1 function"); }
注意:同名变量和同名函数同时存在的时候,分析其执行顺序即可,函数声明第一个执行,其他代码顺序执行。
//同名变量和同名函数同时存在的时候, //分析其执行顺序即可,函数声明第一个执行, //其他代码顺序执行。 var f1="subject"; f1(); function f1(){ console.log("I am f1 function"); } //Uncaught TypeError: f1 is not a function f1();//I am f1 function var f1="subject"; console.log(f1);//subject function f1(){ console.log("I am f1 function"); }
3.2 内部环境可以访问外部环境的变量,反之亦然。
环境:每一个函数内部都是一个环境,最外边是全局变量
两种类型:函数环境、全局环境
var week="Sunday"; function f1(){ var weather="sunshine"; console.log("星期:"+week); //星期:Sunday } f1(); console.log("气候:"+weather);//Uncaught ReferenceError: weather is not defined
3.3 变量的作用域是声明时决定的,而不是运行时。
//变量的作用域是声明时决定的,而不是运行时 //全局变量,可以同时给f1和f2访问 var week="Sunday"; function f1(){ console.log("星期:"+week); } function f2(){ //局部变量,只能给f2本身子级访问 var week="Monday"; f1();//该f1无论在任何地方访问,都只能访问到Sunday的信息 } f2();//星期:Sunday //变量的作用域是声明时决定的,而不是运行时 //全局变量,可以同时给f1和f2访问 var week="Sunday"; function f1(){ console.log("星期:"+week); } week="Monday"; f1();//星期:Monday
3.4 执行环境可以访问变量的类型和优先级
//执行环境可以访问变量的类型和优先级 //形参<外部变量 //形参优先级高 var week="Sunday";//外部变量 function f1(){ function f2(week){//形参 console.log("星期:"+week); } f2("Monday"); } f1();//星期:Monday