前端入门学习笔记(二十三)JavaScript入门(六)函数、函数表达式、箭头函数、函数调用(参数相关)、JS函数中的大坑

本文介绍了JavaScript函数的命名规范,函数的创建方式包括函数声明、函数表达式和箭头函数,并详细讲解了如何处理过多参数、使用rest参数和arguments对象。此外,讨论了回调函数的使用、对象属性作为参数的优点以及函数中的return语句和变量声明提前带来的潜在问题。

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

1.函数的命名

函数是行为。所以它们的名字通常是动词。它应该简短且尽可能准确地描述函数的作用。这样读代码的人就能得到正确的线索。
一种普遍的做法是用动词前缀来开始一个函数,这个前缀模糊地描述了这个动作。团队内部必须就前缀的含义达成一致。

例如,以 “show” 开头的函数通常会显示某些内容。
“get…” —— 返回值,
“calc…” —— 计算
“create…” —— 创建,
“check…” —— 检查并返回 boolean 值,等。
下面列举几个例子

showMessage(..)     // 显示信息
getAge(..)          // 返回 age (gets it somehow)
calcSum(..)         // 计算求和并返回结果
createForm(..)      // 创建表格 (通常会返回它)
checkPermission(..) // 检查权限并返回 true/false

2.函数创建的方式(函数声明、函数表达式、箭头函数)

方式一(函数声明)

function abs(x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

方式二(函数表达式)

var abs = function (x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
};

在这种方式下,function (x) { … }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。
上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;,表示赋值语句结束。

方法三(箭头函数)
一些比较简单的方法,比如要创建一个sum()函数,a和b为参数,sum(a,b)可返回a+b的值。
用函数表达式的话大致是这样的代码

var sum = function(a, b) {
  return a + b;
};

而使用箭头函数的话,代码如下所示

 var sum = (a, b) => a + b;

如果我们只有一个参数,那么括号可以省略,甚至更短:

var double = n => n * 2;

有时我们需要一些更复杂的东西,比如多个表达式或语句。这也是可能的,但我们应该把它们装在花括号里。然后在他们内部使用正常的 return。

var sum = (a, b) => {  // 花括号打开多线功能
  var result = a + b;
  return result; // 如果我们使用花括号,使用返回来获得结果
};

3.调用函数

3.1 参数过多
rest变量

调用函数时,按顺序传入参数即可:

abs(10); // 返回10
abs(-9); // 返回9

由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:

abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9

若想要接收多出的参数应该怎么做呢,在ES6前有arguments(不过箭头函数中没有arguments),这里要用ES6后提供的rest 参数,它的操作符表示为3个点 …,且Rest 参数必须放到参数列表的末尾

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
“arguments” 变量

函数的上下文会提供一个非常特殊的类数组对象 arguments,所有的参数被按序放置。

例如:

 function showName() {
  alert( arguments.length );
  alert( arguments[0] );
  alert( arguments[1] );

  // 它是可遍历的
  // for(let arg of arguments) alert(arg);
}

// 依次弹出提示:2,Julius,Caesar
showName("Julius", "Caesar");

// 依次弹出提示:1,Ilya,undefined(不存在第二个参数)
showName("Ilya");

在 JavaScript 引入 Rest 参数之前,无论入参数是多是少,想获取所有的入参只能使用 arguments。

时至今日,这仍是一个可用的方法。

即使 arguments 是一个类数组且可遍历的变量,但它终究不是数组。它没有数组原型链上的函数,我们没法直接调用诸如 arguments.map(…) 等这样的函数。

同样的,因为它总是包含所有的参数,我们并不能像使用 Rest 参数一样,期望它只截取入参的一部分。

因此如果你不想受困于以上“缺点”,那么赶紧使用 Rest 参数吧。


3.2 回调函数

使用函数表达式传递函数。
我们写一个包含三个参数的函数 ask(question, yes, no):
question 是文本
yes 是当回答 “Yes” 时候运行的脚本
no 是当回答 “No” 时候运行的脚本
函数需要提出 question(问题),依赖用户的回答, 调用 yes() 或 no():

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "You agreed." );
}

function showCancel() {
  alert( "You canceled the execution." );
}

ask("Do you agree?", showOk, showCancel);

在这里插入图片描述
点击确定
点击取消
点击确定则调用showOK,点击取消则调用showCancel
例子中,showOk 对应回答 “yes” 的回调,showCancel 对应回答“否”。

当然此处我们可以使用函数表达式进行简写,效果与上面的代码相同

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

ask(
  "Do you agree?",
  function() { alert("You agreed."); },
  function() { alert("You canceled the execution."); }
);

3.3 将对象属性用于做实参

将对象属性用作实参, 从而不必记住参数的顺序.

function arraycopy(from, from_start, to, to_start, length) {
    for (var i = from_start, j = to_start; i < from_start + length; ++i, ++j) {
        to[j] = from[i];
    }
}

function easycopy(args) {
    arraycopy(args.from,
        args.from_start || 0, //default param
        args.to,
        args.to_start || 0,
        args.length);
}
var a = [1, 2, 3, 4],
    b = [];
easycopy({
    from: a,
    from_start:1,
    to: b,
    length: 3
});
console.log(b); // [ 2, 3, 4 ]

当使用对象属性作为参数时,IDE会提示属性名。
在这里插入图片描述
以对象属性名作为参数的做法,虽然实现效率较低,但是不必再去记住实参的顺序。


4. 函数中的return语句(坑)

要小心了,由于JavaScript引擎在行末自动添加分号的机制,上面的代码实际上变成了:

function foo() {
    return; // 自动添加了分号,相当于return undefined;
        { name: 'foo' }; // 这行语句已经没法执行到了
}

所以正确的多行写法是:

function foo() {
    return { // 这里不会自动加分号,因为{表示语句尚未结束
        name: 'foo'
    };
}

5. JavaScript中的变量声明提前(坑)

如果按照我的思维理解,以下的输出应该是1 1 2,而实际上,会输出1 undefined 2

"use strict";
var x = 1;
console.log(x);//输出 1
var A = function() {
   console.log(x);//看起来像会输出全局变量 x,即1,实际上输出undefined
  var x = 2;
  console.log(x);//输出 2
}
A();

这个是为什么呢?因为JavaScript编译器在编译的时候,会将A body内的声明变量提到最前,所以实际上的执行代码是这样的

"use strict";
var x = 1;
console.log(x);//输出 1
var A = function() {
   var x;
   console.log(x);//看起来像会输出全局变量 x,即1,实际上输出undefined
  x = 2;
  console.log(x);//输出 2
}
A();

声明了x,但是没有对齐进行赋值,故输出undefined。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值