Function 对象

11、Function 对象

函数在程序中代表的就是一段具有功能性的代码,可以让我们的程序编程更加具有结构性和提升程序的复用性,也能让代码变得更加灵活强大

11.1、声明函数

// 函数的定义方式1
function 函数名 (参数){
    函数体;
    return 返回值;
}
功能说明:
    可以使用变量、常量或表达式作为函数调用的参数
    函数由关键字function定义
    函数名的定义规则与标识符一致,大小写是敏感的
    返回值必须使用return
    
//  函数的定义方式2
    
用 Function 类直接创建函数的语法如下:
var 函数名 = new Function("参数1","参数n","function_body");
​
虽然由于字符串的关系,第二种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。    
   

11.2、函数调用

    //f(); --->OK
    function f(){
        console.log("hello")
​
    }
    f() //----->OK
​

不同于python,js代码在运行时,会分为两大部分———预编译 和 执行阶段。

  • 预编译:会先检测代码的语法错误,进行变量、函数的声明。

  • 执行阶段:变量的赋值、函数的调用等,都属于执行阶段。

11.3、函数参数

(1) 参数基本使用

// 位置参数
function add(a,b){
    console.log(a);
    console.log(b);
}
add(1,2)
add(1,2,3)
add(1)
​
// 默认参数
function stu_info(name,gender="male"){
    console.log("姓名:"+name+" 性别:"+gender)
}
​
stu_info("yuan")

(2)函数中的arguments对象

function add(a,b){
​
        console.log(a+b);//3
        console.log(arguments.length);//2
        console.log(arguments);//[1,2]
​
    }
add(1,2)
​
// arguments的应用1 
function add2(){
    var result=0;
    for (var num in arguments){
        result+=arguments[num]
    }
    console.log(result)
​
}
​
add2(1,2,3,4,5)
​
// arguments的应用2
​
function f(a,b,c){
    if (arguments.length!=3){
        throw new Error("function f called with "+arguments.length+" arguments,but it just need 3 arguments")
    }
    else {
        alert("success!")
    }
}
​
f(1,2,3,4,5)
​

11.4、函数返回值

在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。

function add(x,y) {
          return x+y
      }
​
var ret = add(2,5);
console.log(ret)

1、在函数体内可以包含多条 return 语句,但是仅能执行一条 return 语句

2、函数的参数没有限制,但是返回值只能是一个;如果要输出多个值,可以通过数组或对象进行设计。

11.5、匿名函数

匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。

      // 匿名函数赋值变量
       var foo = function () {
           console.log("这是一个匿名函数!")
       };
​
      // 匿名函数的自执行
      (function (x,y) {
           console.log(x+y);
       })(2,3)
​
​
     // 匿名函数作为一个高阶函数使用
     function bar() {
​
        return function () {
            console.log("inner函数!")
        }
    }
​
    bar()()
        

使用匿名函数表达式时,函数的调用语句,必须放在函数声明语句之后!

11.6、函数作用域

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理。

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

// 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
// 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉

首先熟悉下var

    var name = "yuan"; // 声明一个全局变量 name并赋值”yuan“
    name = "张三";  // 对已经存在的变量name重新赋值 ”张三“
    console.log(name);
​
    age = 18   // 之前不存在age变量,这里等同于var age = 19 即声明全局变量age并赋值为18
​
    var  gender = "male"
    var  gender = "female" // 原内存释放与新内存开辟,指针指向新开辟的内存
    console.log(gender)

作用域案例:

 var num = 10; // 在函数外部声明的变量, 全局变量
    function func(){
        // num = 20; // 函数内部直接使用变量,则默认调用了全局的变量,
        //var num = 20; // 函数内部使用var 或者 let声明的变量则是局部变量
                  // 函数内部直接使用变量,则默认调用了全局的变量,
                  // 使用变量的时候,解释器会在当前花括号范围值搜索是否有关键字var 或者 let 声明了变量,如果没有,则一层一层往外查找最近的声明
                  // 如果最终查找不到,则直接报错! 变量名 is not define!
        console.log("函数内部num:",num)
    }
func();
console.log("全局num:",num);

11.7、JS的预编译

js运行三个阶段:

  1. 语法分析

  2. 预编译

  3. 解释执行

语法分析就是JS引擎去检查你的代码是否有语法错误,解释执行就是执行你的代码。最重要最需要理解的就是第二个环节预编译,简单理解就是在内存中开辟一些空间,存放一些变量与函数 。

预编译可分为全局预编译和局部预编译。

  1. 在js脚本加载之后,会先通篇检查是否存在低级错误;

  2. 在语法检测完之后,便进行全局预编译;

  3. 在全局预编译之后,就解释一行,执行一行;

  4. 当执行到函数调用那一行前一刻,会先进行函数预编译,再往下执行。

全局预编译的3个步骤:

  1. 创建GO对象(Global Object)全局对象,即window对象。

  2. 找变量声明,将变量名作为GO属性名,值为undefined

  3. 查找函数声明,作为GO属性,值赋予函数体

局部预编译的4个步骤:

  1. 创建AO对象(Activation Object)执行期上下文。

  2. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

  3. 将实参值和形参统一。

  4. 在函数体里面找函数声明,值赋予函数体。

GO对象是全局预编译,所以它优先于AO对象所创建和执行

案例分析:

  <script>
        var a = 10;
        console.log(a);
​
        function foo(a) {
          console.log(a);
          var a = 100;
          console.log(a);
          function a() {}
          console.log(a);
          var b = function(){};
          console.log(b);
          function d() {}
        }
        var c = function (){
        console.log("匿名函数C");
        };
        console.log(c);
        foo(20);
​
  </script>
​
全局预编译
​
    GO/window = {
        a: undefined,
        c: undefined,
        foo: function(a) {
            console.log(a);
            var a = 123;
            console.log(a);
            function a() {}
            console.log(a);
            var b = function() {}
            console.log(b);
            function d() {}
        }
    }
解释执行代码(直到执行调用函数foo(20)语句)
GO/window = {
        a: 10,
        c: function (){
            console.log("I at C function");
        }
        test: function(a) {
            console.log(a);
            var a = 123;
            console.log(a);
            function a() {}
            console.log(a);
            var b = function() {}
            console.log(b);
            function d() {}
        }
    }
调用函数foo(20)前发生布局预编译
// 局部预编译前两步:
AO = {
        a:undefined,
        b:undefined,
    }
​
// 局部预编译第三步:
AO = {
            a:20,
            b:undefined,
        }
// 局部预编译第四步:
AO = {
        a:function a() {},
        b:undefined
        d:function d() {}
    }

预编译总结:

  1. 函数声明整体提升-(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)

  2. 变量 声明提升-(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined)

面试题:

​
var num3 = 10;
function func3(){
    console.log(num3); 
    var num3 = 20;       
}
func3();
console.log(num3); 
​
​
 /*
​
        // 全局编译
​
        GO{
           num3:undefined,
           func3: function (){
            console.log(num3);
            var num3 = 20;
        }
​
        // 全局执行
        var num3 = 10;
        GO{
           num3:10,
           func3: function (){
            console.log(num3);
            var num3 = 20;
        }
​
​
        // 局部编译
        func3.AO{
           num3:undefined,
        }
​
​
        // 局部执行
​
        func3.AO{
           num3:20,
        }
​
        // 全局执行
​
        GO.num3 = 10
        }
​
*/
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值