JavaScript(4)-函数

本文详细介绍了JavaScript中的函数定义,包括自定义函数和匿名函数,以及Function构造函数。讨论了函数提升和自调用函数的概念。接着讲解了函数参数,区分了显式参数和隐式参数,并介绍了arguments对象。最后阐述了函数的四种调用方式,特别是this关键字在不同调用方式下的指向。内容涵盖了函数的基础知识和深入理解。
摘要由CSDN通过智能技术生成

一、函数定义

函数是完成某一个具体功能的代码块。

JavaScript 使用关键字 function 定义函数。

1. 声明函数

函数有两种声明方式:

1)自定义函数方式(命名函数)

利用函数关键字 function 自定义函数

// 声明函数
function functionName(parameters) {
  执行的代码
}  // 不以分号结束
// 调用函数
functionName(); 
  • function——声明/定义/创建函数的关键字【标志】
  • functionName——函数名称【自己定义】
  • (parameters)——参数列表/传递参数【参数是引入函数之外的数据进入本函数】
  • {}——函数体,包含具体功能的实现代码

函数声明后不会立即执行,在需要的时候去调用后才会执行

分号是用来分隔可执行JavaScript语句。
由于函数声明不是一个可执行语句,所以不以分号结束。

// 案例1:自定义函数
function test1(a, b) {
  return a * b;
}
var x = test1(4, 5);  // 有返回值,声明一个变量x保存返回值
console.log('案例1的x是:' + x);  // 20

2)函数表达式方式(匿名函数)

JavaScript 函数可以通过一个表达式定义。

var fn = function(){...};  // 匿名函数后面跟分号结束
fn();  // 函数调用必须写到函数体下面
  • fn 是变量名,不是函数名
  • 因为函数没有名字,所以也被称为匿名函数
  • 这个 fn 里面存储的是一个函数 ,而不是值
  • 函数调用的代码必须写到函数体后面

匿名函数以分号结尾,因为它是一个执行语句。

// 案例2:函数表达式
var x = function (a, b) {
  return a * b;
}
console.log('案例2的x是:' + x);  // 变量x里面存储的是函数,不是一个值
console.log(x(3, 4));  // 把变量x当做函数名来调用函数,得到函数的执行结果 12

在这里插入图片描述

2. Function() 构造函数

创建函数有2种方式:

  1. 通过关键字 function 定义(即以上我们学习过的,关键字function是小写的)
  2. 通过内置的 JavaScript函数构造器Function()定义(构造函数Function首字母是大写的)
// 案例3:构造函数
var test2 = new Function('a', 'b', 'return a*b');  // 参数、函数执行代码都写在()内
var res = test2(5, 6);  // 传参并调用函数,将返回结果保存在变量res中
console.log(res);  // 30

3. 函数提升

函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

fn();
function fn() {
    console.log('打印');
}

结果:控制台打印字符串 — ”打印“

注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!

函数表达式声明函数问题

函数表达式创建函数,会执行变量提升,而不是函数提升。

fn();
var fn = function() {
    console.log('想不到吧');
}

结果:报错提示 ”fn is not a function"

解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用。

// 相当于:
var fn;
fn();
fn = function() {
    console.log('想不到吧');
}

4. 自调用函数

  • 不能自调用声明的函数。

  • 函数表达式可以 “自调用”。

  • 通过添加括号,来说明它是一个函数表达式。

  • 表达式后面紧跟 () ,则会自动调用。

(function () {
  console.log('我是自己调用的'); // 把整个函数用()括起来,表示它是一个函数表达式
})(); // 表达式后面紧跟(),自动调用函数

以上函数实际上是一个 匿名自我调用的函数 (没有函数名)。

5. 函数是对象

在 JavaScript 中使用 typeof 操作符判断函数类型将返回 “function” 。

但是JavaScript 函数描述为一个对象更加准确,因为函数有 属性方法

// 案例5:函数有属性和方法 
function test5(a, b, c) {
  return arguments.length;
}
// arguments.length 属性返回函数调用过程接收到的参数个数:
console.log(test5(7, 8, 9));  // 3 接收到的参数个数是3个
// toString() 方法将函数作为一个字符串返回:
console.log(test5.toString());

在这里插入图片描述

二、函数参数

参数是引入函数之外的数据进入本函数进行元素的变量

1. 显式参数(Parameters)与隐式参数(Arguments)

  • 函数显式参数——在函数定义时列出。
  • 函数隐式参数——在函数调用时传递给函数真正的值。
function test1(name, age) {  // name,age 是显示参数
  return name + ',' + age;
}
console.log(test1('张三', 25));  // '张三',25是隐式参数

2. arguments 对象

arguments 是 JavaScript 函数的一个内置对象,包含了函数调用的参数数组。

  • 具有 length 属性
  • 按索引方式储存数据
// 案例2:找参数里的最大值
function findMax() {
  var max = arguments[0];  // 把数组里的第一个数当做最大的,用变量max保存起来
  for (var i = 0; i < arguments.length; i++) {
    if (arguments[i] > max) {  // 用数组里的每一个数和max去比,当哪一个>max时,
      max = arguments[i];   // 就把这1个赋值给max,从而保证max的值就是最大的那个
    }
  }
  return max;
}
var res = findMax(5, 6, 80, 99, 32, 41);
console.log(res);  // 99
// 案例3:求数组中的最大值
function getArrMax(arr) {
  var max2 = arr[0];
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] > max2) {
      max2 = arr[i];
    }
  }
  return max2;
}
var res2 = getArrMax([5, 6, 80, 99, 32, 41]);
console.log(res2);  // 99
// 案例4:求所有数值的和
function sumAll() {
  var sum = 0;
  for (var i = 0; i < arguments.length; i++) {
    sum = sum + arguments[i]; 
  }
  return sum;
}
var x = sumAll(2, 6, 66, 8, 12, 30, 44,);
console.log('这些数的和是:' + x);  // 168

3. 通过值传递参数

  • 在函数中调用的参数是函数的隐式参数。
  • 隐式参数通过值来传递:函数仅仅只是获取值。
  • 如果函数修改参数的值,不会修改显式参数的初始值(在函数外定义)。
  • 隐式参数的改变在函数外是不可见的。

4. 通过对象传递参数

  • 在JavaScript中,可以引用对象的值。
  • 因此我们在函数内部修改对象的属性就会修改其初始的值。
  • 修改对象属性可作用于函数外部(全局变量)。
  • 修改对象属性在函数外是可见的。
function test5(name, age) {
  return name + ',' + age;
}
var re = test5('李四', 28);  // '李四', 28--是参数的具体值【值传递】
var canshu1 = '王五';
var canshu2 = 30;
console.log(canshu1.charAt(0));  // 王 canshu1有charAt()方法,canshu1变量就是对象
var res = test5(canshu1, canshu2);  // 参数是变量,它有方法,参数也是对象--【对象传递】
console.log(res); // 王五,30

三、函数调用

函数中的代码在函数被调用后执行,JavaScript 函数有 4 种调用方式。

每种方式的不同在于 this 的初始化。

this 关键字

一般而言,在Javascript中,this指向函数执行时的当前对象。

1. 作为一个函数调用

// 案例1:全局函数
function test1(a, b) {
  return a * b;
}
console.log(test1(10, 5));  // 50
console.log(window.test1(10, 5));  // 50
console.log(this);  // this指向的是Window
  • 以上函数不属于任何对象。
  • 但是在 JavaScript 中它始终是默认的全局对象。
  • 在 HTML 中默认的全局对象是 HTML 页面本身,所以函数是属于 HTML 页面。
  • 在浏览器中的页面对象是浏览器窗口(window 对象),所以以上函数会自动变为 window 对象的函数。
  • 所以test1() 和 window.test1() 是一样的。
  • 以上案例1返回 this 的值是 window 对象

全局对象

当函数没有被自身的对象调用时 this 的值就会变成全局对象。

在 web 浏览器中全局对象是浏览器窗口(window 对象)。

2. 函数作为方法调用

可以将函数定义为对象的方法。

var obj = {
  firstName: '张',
  lastName: '三',
  fullName: function () {
    return this.firstName + this.lastName;  // this指向obj对象
  }
}
document.write(obj.fullName());  // 张三

函数作为对象方法调用,会使得 this 的值成为对象本身。

3. 使用构造函数调用函数

如果函数调用前使用了 new 关键字, 则是调用了构造函数。

这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象。

function test3(a, b) {
  this.firstName = a;
  this.lastName = b;
}
var x = new test3('李', '四')  // 构造函数的调用会创建一个新的对象x
document.write(x);  // [object Object]
document.write(x.firstName);  // 李  新对象x继承了构造函数的属性

构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。

4. 作为函数方法调用函数

在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。

function test4(a, b) {
  return a * b;
}
var myObj;
myObj = test4.call(myObj, 5, 6);  // call传入的是实际参数 第一个参数必须是对象本身
document.write(myObj);  // 30 
var myArr = [7, 8];
myObj = test4.apply(myObj, myArr);  // apply传入的是一个参数数组 第一个参数必须是对象本身
document.write(myObj);  // 56
  • call()apply() 是预定义的函数方法。

  • 可用于调用函数,第一个参数必须是对象本身。

  • 两个方法都使用了对象本身作为第一个参数。

  • 两者的区别在于第二个参数:

    • apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入
    • 而call则作为call的参数传入(从第二个参数开始)
  • 在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。

  • 在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。

通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值