1.变量声明提升:
console.log(a); //undefined
var a = 123;
此处的变量声明部分会被提升,赋值部分不会被提升(相当于没有给a赋值),所以输出undefined;
a = "hello";
console.log(a) //hello
var a = 123;
改动之后,将a赋予一个值,这样才会有输出;
2.函数表达式提升:
console.log(a()) //直接报错
var a = function(){
return "hello"
}
console.log(a()) //hello
var a = function b(){
return 123
}
console.log(b()) //直接报错
注意: 函数表达式其实就是变量声明,只不过被赋值的部分是一个函数,所以提升的依然是声明部分,赋值部分不会被提升,否则会报错(也就是函数表达式不能提升);
3.函数声明提升:
console.log(add()) //hello
function add(){
return "hello"
}
console.log(add()) //hello
function str(){
return "hello"
}
console.log(str()); //world
function str(){
return "world"
}
console.log(str()) //world
var a = 2;
function a(a){
console.log(a) //直接报错
}
a(3)
//函数声明和变量声明如果遇到同名,函数声明会被忽略(前者覆盖后者),所以会报错
函数声明会被全部提升,包括函数名,函数体;
如果碰到同名的函数声明,则后者会覆盖前者;如果遇到同名的变量声明,则前者会覆盖后者;
4.变量的重复声明:
var a = 1;
var a = 2;
console.log(a) //2
当变量重复声明时,遵循就近原则,选择最近的进行输出;
5.立即执行函数(并不代表就是闭包):
(function(){
var a = 2;
})()
console.log(a) //直接报错
在这个立即执行函数中,不管传不传参数,函数体内的都是局部变量,所有最后会报错;
var a; //这段代码就相当于在顶部声明了一个没有值的全局变量
(function(){
a = 2; //这里会改变全局变量的值
})()
console.log(a) //2
在这个立即执行函数中,顶部的没有值的全局变量可写可不写;
var a; //全局变量没有赋值
(function(a){
a = 2;
})(a)
console.log(a) //ubdefined
在这个立即执行函数中,传入了参数,此时的函数体内是一个新的作用域,里面是局部变量;
var a = 1;
//console.log(a) //由于没有加分号,直接报错
(function(a){
console.log(a) //1
})(a)
console.log(a) //1
根据作用域查找,立即执行函数体体内没有值,它就会向上查找,找到外面的值,进行输出;
(注意:在写立即执行函数之前,一定要加上分号,否则会报错;)
var a = 1;
(function(a){
console.log(a) //1
a = 3;
console.log(a) //3
var a = 2
console.log(a) //2
})(a)
console.log(a) //1
在这个立即执行函数体内,会形成一个单独的作用域,如果里面的变量赋予了值(相当于重新定义了一个变量),根据作用域查找,会找到自己本身的值进行输出;
(注意:函数体内的变量都是局部变量,函数体外的变量是全局变量)
var foo = {n:1};
(function(foo){
console.log(foo.n) //1
foo.n = 2; //没有重新定义一个变量,仅仅是将foo中的参数的值进行了改变,将参数的值变成了2
console.log(foo.n) //2
})(foo)
console.log(foo.n) //2
在这个立即执行函数中,仅仅是将foo这个对象中的参数的值进行了改变,并没有重新定义一个变量,所以最后输出的就是参数值已经改变了的对象;
var foo = {n:1};
(function(foo){
console.log(foo.n) //1
foo.n = 2;
console.log(foo.n) //2
var foo = {n:3} //重新定义了一个变量,也就是形成一个新的作用域
console.log(foo.n) //3
})(foo)
console.log(foo.n) //2
在这个立即函数中,就是重新定义了一个变量(相当于组成了一个新的作用域);
var foo = {n:1};
(function(foo){
console.log(foo.n) //1
foo.n = 2;
console.log(foo.n) //2
var foo = {n:3} //重新定义了一个变量,也就是形成一个新的作用域
console.log(foo.n) //3
foo.n = 4 //不论怎么改变参数的值,始终改变的是新的作用域的参数
console.log(foo.n) //4
})(foo)
console.log(foo.n) //2
在这个立即执行函数中,已经形成了一个新的作用域,所以在下面无论怎么改动参数的值,只是改动的新的作用域中的参数,与原作用域无关;