进阶3 函数与作用域无标题文章

1. 函数声明和函数表达式的区别
  • 函数声明:不必放在调用的前面
//函数调用
sum();
//函数声明
function sum(){
    var a=1;
    var b=1;
    c=a+b;
    return c;
}
  • 函数表达式:必须放在调用的前面
var sum=function(){
    var a=1;
    var b=1;
    c=a+b;
    return c;
}
sum();
2. 变量的声明前置和函数的声明前置
  • 变量的声明前置:当一个变量被定义时,在代码执行前会先将变量进行初始化再执行语句。
console.log(a);         声明前置后  var a;
var a =1;                         console.log(a);   // undefined
console.log(a);                    a =1 ;                                   
                                   console.log(a);  // 1     

  • 函数的声明前置:当函数以函数声明的方式声明时,代码执行前会首先生成该函数,然后再执行语句
sayHello();                     声明前置后  function sayHello(){
function sayHello(){                           console.log('hello');
    console.log('hello');                  }
}                                          sayHello();  //'hello'
3. arguments

arguments是一个类数组对象,可以传入function内部所有的参数(本地变量),但不是函数的属性,只在函数内部有效,写法是arguments[i]依次对参数进行访问和修改。

function printPersonInfo(name, age, sex){
    console.log(name);
    console.log(age);
    console.log(sex);
    console.log(arguments);
 }
4. 实现函数的"重载"

在js中没有函数的重载,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后出现的会覆盖先出现的,但可以在函数体针对不同的参数调用执行相应的逻辑,或通过arguments实现重载。

  • 通过传入参数实现重载
function userInfo(name,age,sex){ 
    if(name){ 
        console.log(name); 
    } 
    if(age){ 
        console.log(age); 
    } 
    if(sex){
         console.log(sex);
     } 
} 
userInfo("andy",22); //参数依次传递值,缺少的参数返回的是
undefined userInfo("andrea",20,"female");
  • 通过arguments来实现重载
function sum(){
    var  sum =0;
    for (var i =0; i
5. 立即执行函数表达式概念和作用
(function(){
  var a  = 1;
  console.log(a); //1
})()
console.log(a); //报错:Uncaught ReferenceError: a is not defined

其他写法

(function fn1() {
    var a  = 1;
    console.log(a); //1
})();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
// 逗号也只能操作表达式
1, function fn3(){
      var a  = 1;
      console.log(a); //1
}();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
!function(){
  var a  = 1;
  console.log(a); //1
}();
console.log(a); //报错:Uncaught ReferenceError: a is not defined
进阶3 函数与作用域无标题文章_第1张图片
立即执行函数.jpg

作用:隔离作用域,防止了变量的命名冲突,形成独立的空间;可以让函数在定义后直接调用,在固有的作用域内使用,不会污染全局变量

6. 递归实现n!
function factor(n){
    if(n===1||n===0){
        return 1;
    }
    return n*factor(n-1);
}
7. 代码练习
进阶3 函数与作用域无标题文章_第2张图片
以上代码输出什么?
getInfo('饥人谷',2,'男')输出结果:
name:饥人谷
age:2
sex:男
["饥人谷",2,"男"]
name valley
getInfo('小谷', 3)输出结果:
name:小谷
age:3
sex:undefined
["小谷",3]
name valley
getInfo('男')输出结果:
name:男
age:undefined
sex:undefined
["男"]
name valley
8. 写一个函数,返回参数的平方和
 function sumOfSquares(){
     var result=0;
     for(var i=0; i
9. 代码练习
以上代码输出什么?
变量声明前置:
var a;
console.log(a); //underfined,变量声明前置,初始值undefined 
a = 1; 
console.log(b); //报错:Uncaught ReferenceError:b is not defined,因为b没有声明
10. 代码练习
进阶3 函数与作用域无标题文章_第3张图片
以上代码输出什么?
sayName('world')输出结果:
hello world
//函数声明不必放在调用的前面
sayAge(10)输出结果:
报错:Uncaught TypeError: sayAge is not a function
//函数表达式必须放在调用的前面
11. 代码练习

写出以下代码的输出结果和作用域链查找过程伪代码

进阶3 函数与作用域无标题文章_第4张图片
11.png

输出结果:10
作用域链查找过程伪代码:
1.globalContext={
      AO:{
          x:10
          foo:function
          bar:function
      },
      Scope:null
  }
  foo.[[scope]]=globalContext.AO
  bar.[[scope]]=globalContext.AO

2.barContext={
      AO:{
          x:30
      },
      Scope:bar.[[scope]]
  }
  
3.fooContext={
      AO:{},
      Scope:foo.[[scope]]
  }
12. 代码练习

写出以下代码的输出结果和作用域链查找过程伪代码

进阶3 函数与作用域无标题文章_第5张图片
12.png

输出结果:30
作用域链查找过程伪代码:
1. globalContext={
       AO:{
           x:10
           bar:function
       },
       Scope:null
   }
   bar.[[scope]]=globalContext.AO
2. barContext={
       AO:{
           x:30
           foo:function
       },
       Scope:bar.[[scope]]
   }
   foo.[[scope]]=barContext.AO
3. fooContext={
       AO:{},
       Scope:foo.[[scope]]
   }
13. 代码练习

写出以下代码的输出结果和作用域链查找过程伪代码

进阶3 函数与作用域无标题文章_第6张图片
13.png

输出结果:30
作用域链查找过程伪代码:
1. globalContext={
       AO:{
           x:10
           bar:function
       },
       Scope:null
   }
   bar.[[scope]]=globalContext.OA
2. barContext={
       AO:{
           x:30
           function:function
       },
       Scope:bar.[[scope]]
   }
   function.[[scope]]=barContext.OA
3. functionContext={
       AO:{},
       Scope:function.[[scope]]
   }
14. 代码练习

写出以下代码的输出结果和作用域链查找过程伪代码

进阶3 函数与作用域无标题文章_第7张图片
14.png
输出结果:undefined 5 1 6 20 200
作用域链查找过程伪代码:
1. globalContext = { 
        AO:{ 
            a:1 //200
            fn:function 
            fn3:function 
    }, 
   Scope:null 
   } 
   fn.[[scope]] = globalContext.AO 
   fn3.[[scope]] = globalContext.AO

 2.调用fn() 
    fnContext = { 
        AO:{ 
            a:undefined //5,6,20
            fn2:function
        }, 
        Scope:fn.[[scope]] //globalContext.AO 
    }
    fn2.[[scope]] = fnContext.AO 

3. fn3Context = { 
       AO:{ 
           a:200 
       }, 
       Scope:fn3Context.[[scope]] //globalContext.AO 
   } 

4. fn2ConText = { 
       AO:{ 
          a:20
       }, 
      Scope:fn2ConText.[[scope]] //fnContext.AO 
   }

进阶3 函数与作用域无标题文章_第8张图片
注释

你可能感兴趣的:(进阶3 函数与作用域无标题文章)