目录
前言:
今天我们就开始学习JavaScript里面的函数,函数是编程语言的重要组成部分之一,在此之前我们学习过了C语言就知道函数的相关性质了,那下面我们就学习JavaScript里面的函数,对于于C语言又会有那些不同呢。
JavaScript函数
函数是利用特定语法,将一段代码打包在一起,每次调用函数就可以让这个代码块内的代码全部执行,复用代码。
要注意的是,函数跟循环不相似,循环是重复一定次数的执行代码,函数虽然可以重复执行代码,但是它很灵活,可以任意决定它调用的时机
1. 定义函数
JS 函数声明需要以function 关键字开头,之后为要创建的函数名称,function关键字与函数名称之间使用空格分开,函数名之后为一个括号
( )
,括号中用来定义函数中要使用的参数(多个参数之间使用逗号,
分隔开),最后为一个花括号{ }
,花括号中用来定义函数的函数体(即实现函数的代码),如下所示:
//函数声明
function 函数名(参数列表){
// 函数体
return 返回值;
}
函数名自定义,见名知意,命名规范参照变量的命名规范。普通函数以小写字母开头,用于区分构造函数(构造函数使用大写字母开头,定义类)
JavaScript 对于大小写敏感,所以在定义函数时 function 关键字一定要使用小写,而且调用函数时必须使用与声明时相同的大小写来调用函数。
构造函数
构造函数是函数定义的一种,在此之前我们也是学习过了的,在JavaScript里面是通过new去定义一个构造函数
let name=new function('参数1','参数2',……,"执行语句")
不过,这里并不建议去使用构造函数,因为很容易出现一些语法错误,况且也是比较麻烦的,最好还是去所以函数的定义去定义一个函数。
2. 调用函数
一旦定义好了一个函数,我们就可以在当前文档的任意位置来调用它。调用函数非常简单,只需要函数名后面加上一个括号即可。
注意,如果在定义函数时函数名后面的括号中指定了参数,那么在调用函数时也需要在括号中提供对应的参数。
function fun(){
console.log('hello world');
}
//调用函数
fun(); //打印hello world
函数的自执行
函数的自执行就是定义了函数之后让它自动执行,格式如下:
!function(){ 内容 }()
3. 函数的参数
函数的参数分为形式参数和实际参数,简称形参和实参:
形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。
实参即在调用函数时,括号内传入的值。
在调用有参函数时,实参(值)会赋值给形参(变量名)。
这种关系只在函数调用时生效,在调用结束后解除。
参数的默认值:在定义函数时,你可以为函数的参数设置一个默认值,这样当我们在调用这个函数时,如果没有提供参数,就会使用这个默认值作为参数值。
Rest参数:rest是剩余的意思,rest参数是用于函数参数不确定,每次传入的数量都不同,或者函数参数过多,但是又不想写那么多形参的情况,那么rest可以一次性全部接收
4. 函数返回值
在函数中可以使用return语句将一个值(函数的运行结果)返回给调用函数的程序,这个值可以是任何类型。对于有返回值的函数,我们可以会使用一个变量来接收这个函数的返回值。return语句通常在函数的末尾定义,当函数运行到return语句时会立即停止运行,并返回到调用函数的地方继续执行。
return后放了多条数据,只会返回最后一条数据。如果没有去设置return的话,那么函数的返回值默认为undefined
5. 作用域
作用域通俗的说,是变量起作用的范围。因为每个变量都有对应的“生活环境”
JavaScript中作用域主要分为以下几种:
全局作用域(即script标签内的空间)
函数作用域(每个函数的花括号内的部分)
块作用域(除函数外,其他的花括号空间都是块作用域,如if的花括号)
// 此时这里是script内部,所以这个空间是一个全局作用域,在此环境声明的变量为全局变量
let a = 1 // a 为全局变量
let fn = function () {
// 这是函数体内,所以这个小空间是函数作用域
let a = 2 // 此时这个变量a服务与这个空间和这个空间的子空间
console.log(a) // 当前使用的a在这个环境中存在,所以输出 2
{
// 此处,直接写了一个花括号,那么就开启一个独立的空间
// 此时当前空间没有a,所以向上个空间查找,就找到函数内的a,所以输出 2
console.log(a)
}
}
// 此时的console语句是在全局环境执行,所以这里的a不是函数内的,而是全局环境的a 所以输出 1
console.log(a)
let fn2 = function () {
{
// 此时这个块作用域自身空间没有a,向上级空间查找,上级空间是fn2的函数空间,也没有找到,继续向上级查找,在全局空间找到了,所以输出 1
console.log(a)
}
}
查找的规则是,先查找自身,如果查找到就用,就不在向上查找,如果没有依次向上层作用域找,直到找到为止。如果找到全局都没有找到对应名称的变量,则抛出错误
xxx is not defined
。这就是作用域的规则。
6. 匿名函数
匿名函数:省略函数名的函数。语法为:
(function (形参){
})(实参);
7. this指向性问题(重点)
7.1 this的性质
this是一个关键字,js赋予它特殊的意义。指向调用函数的对象,如果没有,则指向window。(意思是说谁调用了这个函数,那么结果就指向谁)
function fn(){
console.log(this); // 指向window
}
fn();
//输出:Window {window: Window, self: Window, document: document, name: '', location: 、Location, …}
下面看个示例:
//创建一个对象
let a={
name:'jack',
fun:function(){console.log(this.name)}//这里的this指向了前面的name属性
}
执行结果:
现在要做的就是这么去实现this的指向进行改变,那么以下的三种方法可以去实现改变this指向,我们接着往下看。
7.2 call的用法
通过JavaScript里面的call函数,我们可以去通过这个函数来去调用其指向的函数并且进行传参操作。其语法为:call(this指向的对象,形参1,形参2……)
看个代码示例:
//call的用法
let a={
fun:function(){
console.log(arguments);//argument是作为参数的储存列表,可以通过打印argument查看参数内容以及数量
return this.name1+this.name2;
}
}
let b={
name1:'蕾',
name2:'姆'
}
var x=a.fun.call(b,486);
console.log(x); //输出:蕾姆
以上是先去创建一个a和b对象,这里我想去通过a里面的函数去指向b对象里面的属性进行调用,于是就可以去通过call函数将b里面的属性被a对象指向然后被调用。
7.3 apply的用法
相似的,apply的语法跟call差不多的,但不同的是参数的传入形式不同,apply只能去通过数组的形式来传入参数,而call是直接传入参数的,apply的格式为:apply(this指向的对象,[数据1,数据2……])
//apply的用法
let a={
fun:function(){
console.log(arguments);
return this.name1+this.name2;
}
}
let b={
name1:'蕾',
name2:'姆'
}
var x=a.fun.apply(b,['艾米莉亚','拉姆']);
console.log(x); //输出:蕾姆
结果:
7.4 bind的用法(了解)
与call不同的是,bind并不会立即执行,其语法是与call一样的。bind的作用仅仅是去改变this的指向而已,并不会去执行这条语句,实际上并没有太大的用处,可以说是基本上不会用到
let a={
fun:function(){
console.log(arguments);
return this.name1+this.name2;
}
}
let b={
name1:'蕾',
name2:'姆'
}
var x=a.fun.bind(b,'大脑在颤抖');
console.log(x);
8.结构赋值(拓展)
之前我们对变量去赋值的时候是一一赋值的,如果我们想一次性去对这些变量进行赋值的话可以去通过结构赋值。
看个示例:
let a,b;
[a,b]=[10,20]; //对a,b依次赋值
console.log(a,b);
[a,b]=[b,a]; //a,b进行数值交换
console.log(a,b);
/*输出结果:10 20
20 10*/
好了,以上就是今天的全部内容了,我们下一期再见!
分享一张壁纸: