重点:参数默认值、函数声明提升、暗示全局变量、预编译、AO、GO
1.参数默认值
默认值为undefined
function test(a = 1,b){ /形参a赋予一个值1
console.log(a);
console.log(b)
}
test(); /输出1 , undefined; 即形参b的默认值为undefined
更改全局的test(),给a赋值undefined 给b赋值2时:
即test(undefined,2) /输出1,2
function test(a = undefined,b){//形参a,b
console.log(a);
console.log(b)
}
test(1,2); /输出1,2
/argument如果赋值为undefined就去找形参上的默认值;如果形参为undefined,argument就去找实参
总结:形参实参中, 谁不是undefined就选谁
<script>
function test(a) {//形参a,b
console.log(a);
console.log(b);
}
test(1, 2); //输出1,以及 ReferenceError: b is not defined
</script>
总结:如果有实参没有形参就会出错,有形参没有实参就会输出默认值:undefined
但是上述方法(在括号内给形参赋值)低版本浏览器不兼容,它是ES6中的新方法。
方法二:
function test(a,b){
var a = arguments[0] || 1; //如果a不存在就返回1
var b = arguments[1] || 2;//如果b不存在就返回2
console.log(a , b);
}
test();
方法三:
function test(a,b){
var a,b;
if(typeof(arguments[0]) !== 'undefined'){
a = arguments[0];
}else{
a = 1;
}
if(typeof(arguments[1]) !== 'undefined'){
b = arguments[1];
}else{
b = 2;
}
console.log(a,b);
}
思路总结
1.如果有实参没有形参就会出错,有形参没有实参就会输出默认值:undefined
2.函数声明提升:
var a;
console.log(a); /输出undefined,因为没有赋值
console.log(a); /输出undefined,此时声明了a,但赋值没有提升上来
var a = 1;
思路总结
函数声明整体提升(提升到整个逻辑代码的最上面),变量只有声明提升,但是赋值是不提升的
所以我们一直强调 var a = 1的步骤为:1. 声明变量a; 2. 将1赋值给a
3.暗示全局变量 (imply global variable)
a = 1;
var b=2;
console.log(a); // 输出 1
实际上在全局里 写不写var 都会声明 都会存储在window对象里面
所以在全局概念里 a = window.a b = window.b
function test(){
var a = 1;
b = 1;
}
test();
console.log(window.b); /输出1
console.log(window.a); /输出undefined
在函数内部,没有声明这个变量,而直接给这个变量赋值的话,那它就提升到全局变量里(存到window里) 内部声明了的 (如上述的a) 还是局部变量
4.预编译
一般代码执行过程:
- 1 通篇检查语法错误
- 1.5 预编译的过程
- 2 解释一行执行一行 预编译:函数执行之前要进行的步骤
function test(a) {
console.log(a); //输出function a(){} 因为此时a还没有赋值
var a = 1;
console.log(a); //输出1
function a() { }
console.log(a); //输出1
var b = function () { }
console.log(b); //输出 function () { }
function d() { }
}
test(2);
}
预编译时产生AO(activation object 活跃对象,也叫函数上下文 )
上述函数步骤:
- 1.创建AO的对象,寻找形参和变量声明 AO = {
a:undefined,
b:undefined } - 2.把实参的数值赋给形参
AO = {
a:undefined --> 2,
b:undefined
} - 3.寻找函数声明,给变量赋值函数体
AO = {
a:undefined --> 2,--> function(){}
b:undefined
d: function d(){} }
预编译执行结束,执行函数:
AO = {
a:undefined --> 2,--> function(){} --> 1
b:undefined -> function(){}
d: function d(){}
}
- 例子:
function test(a,b){
console.log(a);
c = 0;
var c;
a = 5;
b = 6;
console.log(b);
function b(){}
function d(){}
console,log(b);
}
test(1);
//输出1 6 6
最后执行函数时:console.log(a);是第一句,此时不知道a的值,在预编译里面去找,所以 a = 1
console.log(b) 第一个输出6
第二个console.log(b)也是6,因为function b(){}、function d(){}在预编译已经做过了不需要再做。函数执行时,如果之前没有出现var赋值的语句,就会提取预编译里面的函数声明,但是这里之前已经有语句:var b=6;
5. GO
GO:global object 全局上下文
跟AO差不多
1.找变量声明 a : undefined
2.找函数声明 a : undefined 、 function a(){}
最后执行函数:第一句便有了a又赋值1: a : undefined -->function a(){} --> 1
var a = 1;
function a(){
console.log(2);
}
console.log(a); //输出1
其实GO就是window GO===window 它两没区别
window在存储全局变量时也是这么存的
console.log(a,b); /输出 f a(){} , undefined
function a(){}
var b = function(){}、。。。。。
1.寻找变量:b:undefined
2.找函数声明: a: function a(){} ,因为b是函数表达式,所以不会参与此步骤
3.执行函数 :此时 var b = function(){}在后面 所以不会输出function(){}
例子2:
function test(){
var a = b = 1;
console.log(a); //输出1
console.log(b); //输出1
}
test();
1.创立GO
2.AO 找变量声明 AO = {
a: undefined,
}
3.执行函数 看到b了 b没有声明
在GO里面挂着 GO = {
b: 1;
}
4. 执行函数 求a的值 在AO里面去找 找到了a=b--> 去GO里面找 b = 1;故a = 1;
5. 执行函数,求b的值 在AO里面去找 没有--> 去GO里面找 b = 1;
例子3
var b = 1;
function test() {
var a = 1;
var b = 2;
console.log(b);//2
/函数内部自己有,就先找函数内部
}
test();
此例中,证明了执行函数时,先找AO,没找到再去找GO
例子4:
var b = 3;
console.log(a); //大函数
function a(a){
console.log(a); //小函数
var a = 2;
console.log(a); //2
function a() {}
var b = 5;
console.log(b); //5
}
a(1);
1.先执行GO,GO ={
b:undefined
a:function a(){...}
所以第一个console.log(a) 就输出 function a(){...}
执行函数时:没有找到a的值只能去预编译里面找。
}
2.执行AO, AO={
a:undefined; -->1 --> function a(){}
而后面输出2 是因为之前var a=2,后面的function a(){}不看,因为做过了,所以输出2
b:undefined; 执行 b=5;}
例子5:
function test(){
console.log(b);
if(a){
var b = 2;
}
c = 3;
console.log(c);
}
var a;
test();
a = 1;
console.log(a);
//输出 undefined 3 1
-
GO = { a : undefined;
test : function test(){} } -
AO={ b:undefined (b要变量声明,因为此时if语句没有执行,此时不看if,只看有没有变量声明)
} -
c没有var 提升到全局中去:
GO = { a : undefined;
test : function test(){}
c:3
}
6. 实战
<script>
function test(){
return a;
a = 1;
function a(){}
var a = 2
}
console.log(test()); //输出function a(){}
</script>
执行时第一句就是return,此时直接返回预编译最后时 a 的值
<script>
a = 1;
function test(e) {
function e() { }
arguments[0] = 2;
console.log(e);//2
if (a) {
var b = 3;
}
var c;
a = 4;
var a;
console.log(b);//undefined
f = 5;
console.log(c);//undefined
console.log(a);//4
}
var a;
test(1);
//GO: {
// a:undefined->1 ,
//test:function test(){...}
// }
//AO:{
//e:undefined ->function ->1 ->2
//b:undefined (if(a)时,a的值还是为undefined,所以不执行该语句)
//c:undefined
//a:undefined ->4
//AO中 a有值为undefined 主要是变量声明了 不需要去人家GO里面找
</script>
AO中 a变量声明了 不需要去人家GO里面找
此例中 function test(e) 即形参只有一个,为e