7.JavaScript学习笔记——函数

函数

JavaScript代码要求高内聚、弱耦合,函数的封装性有助于降低代码的耦合性。

1. 定义

函数对任何语言来说都是核心组件,因为它们可以封装语句,然后在任何地方、任何时间执行。ECMAScript中的函数使用function关键字声明,后跟一组参数,然后是函数体。

函数的定义方式有以下几种:

  • 函数声明;
  • 命名函数表达式;
  • 匿名函数表达式。

1.1 函数声明

function theFristName() {
    
}

函数实际上也是一个变量,函数的声明关键词是function。

函数名规范命名方式是小驼峰命名法,首字母小写,其他相连单词首字母大写。

1.2 函数表达式

//命名函数表达式
var test = function abc() {

}

函数表达式型定义方法,=后面的代码属于表达式,表达式会忽略其名字。这里的函数名是是abc,但是abc这里并没有什么作用。

相当于

//匿名函数表达式
var test = function () {

}

匿名函数又称为拉姆达函数。

由于用匿名表达式赋值变量的方式比较常见,所以函数表达式定义默认为匿名函数表达式定义。

2. 组成形式

2.1 函数名称

2.2 参数

ECMAScript 函数的参数跟大多数其他语言不同。 ECMAScript 函数既不关心传入的参数个数,也不关心这些参数的数据类型。定义函数时要接收两个参数,并不意味着调用时就传两个参数。你可以传一个、三个,甚至一个也不传,解释器都不会报错。主要是因为 ECMAScript 函数的参数在内部表现为一个数组。

2.2.1 形参

函数定义时的形参,相当于在函数体中写了若干var 形参

2.2.2 实参

形参和实参的数量可以不一致。

未被传递参数的形参,初始值为undefined

无论函数实参有没有传递给形参,函数内都构建了一个argument(实参列表将实参存放在内。

红宝书:在使用 function 关键字定义(非箭头)函数时,可以在函数内部访问 arguments 对象,从中取得传进来的每个参数值。

arguments 对象是一个类数组对象(但不是 Array 的实例),因此可以使用中括号语法访问其中的元素(第一个参数是 arguments[0],第二个参数是 arguments[1])。而要确定传进来多少个参数,可以访问 arguments.length属性。

若要求形参的参数数量,可以访问 函数名.length属性。

function sum(a) {
    console.log(arguments.length);  //3
    console.log(sum.length);    //1
}

sum(4, 5, 6);

在函数内,arguments[i]和第i+1个形参的值是同步变化的,但是他们在内存中是分开的。

function sum(a, b) {
    a = 2;   //
    argument[0] = 3;
}

sum(1, 2);

但是,若实参数小于形参数,多出的实参是没有映射关系的。

function sum(a, b) {
    //arguments  [1]
    b = 2;
    console.log(arguments[1]);  //undefined
}
sum(1);

2.3 返回值

return函数的结束条件加返回值。

函数体中没写return时,程序会自动隐式加上return,以终止函数

return的作用:

1.终止函数

function sum(a, b){
    console.log('a');
    return;
    console.log('b');
}
sum(1);

此时,函数的执行结果是在控制台只打印出字符串a。

2.返回值

function sum(a, b){
    console.log('a');
    return 123;
    console.log('b');
}
var c = sum(1);  //c = 123
function myNumber(target) {
    return +target;
}
var num = myNumber("123");
console.log(typeof(num) + " " + num);   //number  123

3. 全局变量和局部变量

函数内部定义的变量是局部变量,在此函数以外的部分均不能访问该变量。

script标签内直接定义的变量为全局变量,在函数内可以访问。

4. 作用域

定义:变量(变量作用域又称为上下文)和函数生效(能被访问)的区域。

每一个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但是有些不可以,这些不能访问的属性仅供JavaScript引擎存取。

[[scope]]属性就是不可访问的属性之一。

[[scope]]指我们所说的作用域,其中存储了执行期上下文的集合。

4.1 执行期上下文

在函数执行的前一刻,会创建一个称为执行期上下文的内部对象。

一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,它所产生的执行期上下文被销毁。

4.2 作用域链

[[scope]]中存取的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

在函数中查找变量,从作用域链中找,并从顶端以此向下查找。

5. 递归

例如实现阶乘的函数,为了更符合人的逻辑,可以使用递归的思想编写。

function mul(n) {
    if(n == 1 || n == 0) {            //出口
        return 1;
    }
    return n * mul(n - 1);  //规律
}

实现递归的两个要素:

  1. 找规律
  2. 找出口

上例中,阶乘的规律就是n! = n * (n - 1)!,而出口就是当n = 1时,n! = 1。

若没有出口,return语句将求不出一个确定的值而陷入死循环。

规律一定是写在return后面的。

递归的唯一优点就是使代码更加简洁。递归的运算速度很慢,复杂的程序不能用递归。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值