js 函数和变量的提升
1. 函数的作用域:
js中 ,函数的作用域为函数,而不是大括号。
var hei = 123;
if(true){
hei = 456;
}
console.log(hei);// 456;
var hei = 123;
if(true){
(function(){ var hei = 456;})();
}
console.log(hei); // 123
函数内部可以用用函数外部的变量,而函数外部的不可以用函数内部的变量(可以用闭包实现效果,随后总结)。
(function(){ var hei = 456;})(); 为函数自执行函数;有三种:
1) (function(){})();
2) (function(){}());
3) !function(){}();
2. 变量的提升:
var a = 1;
var b = 100;
function z(){
console.log(b); //100 //为什么b没有输出undefined ,这是因为后面没有var b = 99; 而是 b = 99;所以没有提升,他是一个全局变量。函数外也可以用。
console.log(a); //undefined
var a = 10; //所谓提升,就是将var a; 提升到函数体的第一句。就导致了 第二句输出undefined
console.log(a); //10
a = 4;
b = 99; // 如果变成var b = 99;函数外就不能用了 外面的输出就变成了 100. 前面的输出就变成了undefined,因为变量提升。
console.log(a); //4
console.log(b); //99
}
z();
console.log(b); //99
if(false){
var i = 10;
}
console.log(i); //为什是undefined ,也是变量提升。
3.函数提升
首先要明确两点:
<1> 只有函数声明才会进行函数提升
<2> 函数提升会将函数体一起提升上去,这点与变量提升有所不同
下面来证明函数表达式不能进行函数提升:
~function() {
alert(typeof next); // undefined
~function next() {
alert(typeof next); // function
}()
}()
函数前面加个~的目的是将函数声明变成函数表达式,实际上也可以加其它运算符,比如+,-,!等,总之这个函数声明被变成了函数表达式。
从打印结果来看第一个alert出的是undefined,说明next根本没有发生函数提升。
下面来接着验证:
a();// 123
var a = function(){
console.log(321);
}
a();// 321
function a(){
console.log(123);
}
从结果可以看出,先打印出来的反而是放在后面的a(),上面代码的等价表示如下: var a = function a(){
console.log(123);
}
a();
a = function(){
console.log(321);
}
a(); 都可以证明表达式不提升,而函数提升。 4.那么如果当变量提升与函数提升同时发生的时候,哪个的优先级更高呢?我们来做个实验:
console.log(ggg); // function ggg(){}
var ggg = 222;
function ggg(){};
console.log(ggg); // 222
console.log(ggg); // function ggg(){}
function ggg(){};
var ggg = 111;
console.log(ggg); //111 function ggg(){};
var ggg;
console.log(ggg); // function ggg(){}
由对上述代码的分析:可以总结出如下规律:(大神博客的总结,看了之后果然清楚了很多)
1)变量声明提升:变量申明在进入执行上下文就完成了。
只要变量在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;
2)函数声明提升:执行代码之前会先读取函数声明,意味着可以把函数申明放在调用它的语句后面。
只要函数在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;
3)变量or函数声明:函数声明会覆盖变量声明,但不会覆盖变量赋值。
同一个名称标识a,即有变量声明var a,又有函数声明function a() {},不管二者声明的顺序,函数声明会覆盖变量声明,也就是说,此时a的值是声明的函数function a() {}。注意:如果在变量声明的同时初始化a,或是之后对a进行赋值,此时a的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a); //1
**********************************************
接下来会有些 头疼 想了好长好长时间 /(ㄒoㄒ)/~~ var zzz = 222;
function zzz(){
console.log(111);
}
console.log(zzz); // 111
**********************************************
var zzz;
function zzz(){
console.log(111);
}
console.log(zzz); // function zzz(){console.log(111);}
console.log(zzz()); //111 , undefined
************************************************
B = 100;
function B(){
B = 2;
console.log(B);
}
B(); // B is not a function 由于函数提升,所以带着函数体在 B = 100;之前所以B是一个变量,不是函数
************************************************
B = 100;
var B = function(){
B = 2;
console.log(B);
}
B(); //2 由于表达式不提升,所以输出B = 2; 然后我好奇为什么B不输出自己本身的函数,所以把B = 2;改成了 x = 2;然后输出了 function(){ x = 2; console.log(B);}
****************************************************
在大神的博客上看到的小习题:
var a = 1;
function b() {
console.log(a);
a = 10;
function a() {}
}
b();// ?
console.log(a);// ?
我的答案: undefined ,1
运行后的结果: function a(){} ,1 //我的天啊 ,又忘记考虑b函数里a函数的提升了并且覆盖了没赋值的a a = 10;
(function a(){
a = 1;
console.log(a);// ?
})(); 我的答案: 1
运行后结果: function a(){ a = 1; console.log(a);} // 这里自执行函数,首先他是一个表达式,他不会提升,同时声明函数和变量,以函数为主,返回函数
******************************************************
function a(i) {
console.log(i);// ?
var i = 1;
console.log(i);// ?
};
a(10);
我的答案: 10 , 1
运行后结果: 10 , 1 呵呵呵 我终于对一个了。