JavaScript语法引用数据类型之函数(Fuction)

本文详细讲解了JavaScript函数的定义、属性、方法及调用方式,包括函数内部的arguments和this对象,函数的属性如length和prototype,以及apply和call方法的使用。同时,探讨了new关键字的工作原理和函数调用的不同模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么要使用函数?

  1. 提高代码复用
  2. 便于阅读和交流

二、函数介绍

说起 ECMAScript 中什么最有意思,那莫过于函数了。函数在ECMAScript中属于一等公民。本质上每个函数都是 Function 类型的实例,与其他引用类型一样都可以具有方法和属性.

1、基本介绍

函数是一个可以被其他代码或其自身调用的代码片段,或者是一个指该函数的变量variable 。 .当函数被调用时, 参数arguments 作为输入传递到函数,并且函数可以可选地返回输出。 在 JavaScript JavaScript中函数也是一个对象object.

函数名是作为函数声明或函数表达式的一部分声明的标识符 identifier。函数的作用域scope取决于函数名是一个声明还是表达式。

2、 如何定义函数?

1)声明式定义命名函数
命名函数是具有函数名称的函数:

          function fun() {
               console.log(this.username);
             }

2)表达式: 定义匿名函数 。
匿名函数是一个没有函数名的函数

        var foo = function (a, b) {
            console.log(a, b);
        }

3)构造函数模式

        var foo = new Function();

三、函数内部属性

在函数内部,有两个特殊的对象: arguments 和 this。
1、arguments
arguments是一个类数组,包含着传入函数中的所有参数。虽然 arguments 的主要用途是保存函数参数,但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。
callee实例:

        //求一个数的阶乘
        function factorial(num){
            if (num <=1) {
            return 1;
            } else {
            return num * factorial(num-1)
            }
        }

问题:这个函数的执行与函数名 factorial 紧紧耦合在了一起。
为了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee、

function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}

2、this
1)理解this

    1. 一个关键字, 一个内置的引用变量
    2. 在函数中都可以直接使用this
    3. this代表调用函数的当前对象
    4. 在定义函数时, this还没有确定,只有在执行时才动态确定(绑定)的

2) 如何确定this的值

        1. test()
        2. obj.test()
        3. new test()
        4. test.call(obj)  test.apply(obj)

3)代码实例:

    <script type="text/javascript">
    // 构造函数
    /*
         new做了什么?
            1. 返回一个新的对象
            2. 相对于给构造函数最后一行加了  return this
        */
        function People() {
            this.age = 20;
            this.name = "张三";
            console.log(this)
        }
        var p = new People();
        console.log(p);
        //普通调用
        // this ---> window
        Person();
//      this普通调用(全局)指向窗口window
        console.log(this);
    </script>

四、函数的属性和方法

1、属性
ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个
属性: length 和 prototype 。其中, length 属性表示函数希望接收的命名参数的个数。至于prototype则代表函数的显示原型!

2、方法
每个函数都包含两个非继承而来的方法: apply() 和 call() 。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。

1)apply
语法:

func.apply(thisArg, [argsArray])        

参数:
thisArg
在fun函数运行时指定的this值。
argsArray可选的。
一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。

返回值:
调用的方法的返回值,若该方法没有返回值,则返回undefined

2)call
语法:

fun.call(thisArg, arg1, arg2, ...)

参数:
thisArg
在fun函数运行时指定的this值。
arg1, arg2, ...
指定的参数列表
返回值:
调用的方法的返回值,若该方法没有返回值,则返回undefined

代码实例:

<script type="text/javascript">
            function fun(a,b) {
                console.log("a = "+a);
                console.log("b = "+b);
                //alert(this);
            }

            var obj = {
                name: "obj",
                sayName:function(){
                    alert(this.name);
                }
            };

            /*
             * call()和apply()
             *  - 这两个方法都是函数对象的方法,需要通过函数对象来调用
             *  - 当对函数调用call()和apply()都会调用函数执行
             *  - 在调用call()和apply()可以将一个对象指定为第一个参数
             *      此时这个对象将会成为函数执行时的this
             *  - call()方法可以将实参在对象之后依次传递
             *  - apply()方法需要将实参封装到一个数组中统一传递
             * 
             *  - this的情况:
             *      1.以函数形式调用时,this永远都是window
             *      2.以方法的形式调用时,this是调用方法的对象
             *      3.以构造函数的形式调用时,this是新创建的那个对象
             *      4.使用call和apply调用时,this是指定的那个对象
             */

            //fun.call(obj,2,3);
            fun.apply(obj,[2,3]);



            var obj2 = {
                name: "obj2"
            };

            /*fun.apply();
            fun.call();
            fun();*/

            //fun.call(obj);
            //fun.apply(obj);

            //fun();

            //obj.sayName.apply(obj2);
        </script>

五、new关键字解析

new 运算符创建一个用户自定义的类型实例或内置类型的实例。

1、语法:
new constructor[([arguments])]
参数:
constructor:一个指定对象实例的类或函数。
arguments:一个用来被constructor 调用的参数列表
2、构造函数实例化

var aar=    new Object(); 构造函数实例化 

实例化构造函数new的操作:

  1. 返回一个新的对象
  2. 将构造函数中的this指向实例化对象。
  3. 在构造函数的最后一行会 return this;

3、创建一个用户自定义的对象需要两步:

  1. 通过编写函数来定义对象类型。
  2. 通过new来创建对象实例。

4、当执行一个new关键字时都会发生些什么?
当代码 new Foo(…) 执行时,会发生以下事情:

  1. 一个继承自 Foo.prototype 的新对象被创建。
  2. 使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
    即判断构造函数返回值的类型:
    1)如果是值类型,就丢弃它,还是返回instance。
    2)如果是引用类型,就返回这个引用类型的对象,替换掉instance。
    3)如果没有写return,相当于return undefined

六、函数调用总结:

1、普通调用:() call() appiy()

2、 构造调用:new fn()

3、立即调用函数表达式(IIFE):(function(){})()
立即调用函数表达式(IIFE)是一个函数, 其在函数被加载到浏览器的编译器之后直接调用的。. 识别IIFE的方法是通过在函数声明的末尾定位额外的左和右括号。

(function foo1() {
    console.log("立即调用函数表达式");
}());
//道格拉斯·克罗克福德的风格


(function foo2() {
    console.log("立即调用函数表达式");
})();

4、回调: 不需要开发者调用

七、函数与数组的结合使用:

1、介绍
Arguments(函数内部属性):不是数组;可实现函数不传参数获取数值。
arguments.callee():获取当前函数的引用。

2、代码实例:

<script type="text/javascript">
            /*
             * 在调用函数时,浏览器每次都会传递进两个隐含的参数:
             *  1.函数的上下文对象 this
             *  2.封装实参的对象 arguments
             *      - arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
             *      - 在调用函数时,我们所传递的实参都会在arguments中保存
             *      - arguments.length可以用来获取实参的长度
             *      - 我们即使不定义形参,也可以通过arguments来使用实参,
             *          只不过比较麻烦
             *          arguments[0] 表示第一个实参
             *          arguments[1] 表示第二个实参 。。。
             *      - 它里边有一个属性叫做callee,
             *          这个属性对应一个函数对象,就是当前正在指向的函数的对象
             *      
             */

            function fun(a,b){
                console.log(arguments instanceof Array);
                console.log(Array.isArray(arguments));
                console.log(arguments[1]);
                console.log(arguments.length);
                console.log(arguments.callee == fun);
                console.log(arguments);
            }

            fun("hello",true);

        </script>

八、使用细节和注意事项:

1、函数没有重载
实参列表可以不用和形参列表进行一对一的匹配,同名函数之间就是后面的覆盖前面的 ,函数没有重载没有重载。

<script type="text/javascript">
        function fn(){
            console.log('a');
        }

        //形式参数
        function fn(a){
            console.log(a);
        }


        //实参列表可以不用和形参列表进行一对一的匹配
        //同名函数之间就是后面的覆盖前面的  没有重载
        fn(1,2,3,4,5,6);


    </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值