资讯专栏INFORMATION COLUMN

【重温基础】4.函数

maxmin / 2239人阅读

摘要:本文是重温基础系列文章的第四篇。系列目录复习资料资料整理个人整理重温基础语法和数据类型重温基础流程控制和错误处理重温基础循环和迭代本章节复习的是中的基础组件之一,函数,用来复用特定执行逻辑。箭头函数不能使用命令,即不能用作函数。

本文是 重温基础 系列文章的第四篇。
今日感受:常怀感恩之心,对人对己。

系列目录:

【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)

【重温基础】1.语法和数据类型

【重温基础】2.流程控制和错误处理

【重温基础】3.循环和迭代

本章节复习的是JS中的基础组件之一,函数,用来复用特定执行逻辑。

1.定义函数

定义函数有两种方法:函数声明函数表达式

1.1 函数声明

也成为函数声明,通常格式为:

function f (a){
    return a + 1;
}

解释:这里声明一个函数 f ,并传入一个参数 a ,当函数执行以后,通过 return 关键字返回了 a+1的值。

参数
当传入的参数是一个数字/字符串等具体的值的时候,若参数的值被改变,不会影响到全局或调用函数。
但如果参数是个对象,若函数内改变的这个参数的属性,则函数外部的这个参数原始的值会被修改。

var leo = {
    age:20
}
function f(obj){
    obj.age = 15;
    obj.name = "leo";
}
f(leo);
console.log(leo); //{age: 15, name: "leo"}
1.2函数表达式

通过定义一个匿名的函数,来赋值给一个变量,通过这个变量来调用这个函数。

var f = function (a){
    return a + 1;
}

但是函数表达式也可以提供函数名,用于函数内部调用,并指代本身,也可以作为调试器堆栈跟踪中识别该函数。

var f = function g(a){
    return n < 2 ? 1 : a*g(a-1);
}

另外,函数表达式声明可以用来根据不同条件,来定义一个函数:

var f;
if(a == 1){
    f = function (){
        return "when a == 1";
    }
}else {
    f = function (){
        return "when a != 1";
    }
}
2.函数调用

函数定义完成后不会自动执行,需要我们通过函数名称来调用,才能真正执行:

var f = function (){
    console.log("ok");
}
f(); // "ok"

另外,函数也可以调用自身,这就是递归过程:

function f (n){
    if( n==0 || n==1) {
        return 1;
    }else {
        return n * f(n-1);
    }
}
// 三目运算
function f (n){
    return (n==0 || n==1)?1: n*f(n-1);
}
3.函数作用域

由于函数只在函数的内部有定义,所以函数内部定义的变量在函数外部不能访问,函数内部就是这个函数的作用域。
当一个父级函数内,还定义了一个子级函数,则这个子级函数可以访问父级函数定义的变量。

// 全局作用域 global scope
var a = 1, b = 2;
function f (){
    return a + b;
}
f(); // 3

function g(){
    var a1 = "leo", b1 = "pingan";
    function hi (){
        return a1 + "和" + b1
    } 
    return hi();
}
g(); // "leo和pingan"
3.1 闭包

闭包是 JavaScript 中最强大的特性之一,并且JS允许函数嵌套。
在一个函数内部在嵌套一个函数,而嵌套的这个函数对外面的函数是私有的,则形成一个闭包,闭包是一个可以自己拥有独立的环境和变量的表达式,通常是函数。
理解一下,前面说的内部函数可以调用外部函数的变量和方法,那么可以这么理解:闭包的函数继承了父级容器函数的参数和变量,即内部函数包含外部函数的作用域
总结一下:

内部函数只能在外部函数中访问;

内部函数形成闭包:可以访问外部函数的参数和变量,但外部函数却不能使用这个内部函数的参数和变量;

function f(a) {
    function g(b){
        return a + b;
    }
    return g;
}
var a1 = f(5);  // ƒ g(b){ return a + b; }
var a2 = a1(6); // 11
var a3 = f(5)(6); // 11

闭包可以给内部函数的变量提供一定的安全保障
另外,闭包还有复杂的用法:

var f = function (name){
    var age ;
    return {
        setName : function (newName){
            name = newName;
        },

        getName : function (){
            return name;
        },

        getAge : function (){
            return age;
        },
        setAge : function (newAge){
            age = newAge;
        }
    }
}

var leo = f("leo");
leo.setName("pingan");
leo.setAge(20);
leo.getName();     // "pingan"
leo.getAge();      // 20
3.2命名冲突

在同一个闭包作用域下若参数或变量名相同,产生冲突,则优先使用作用域最近

function f(){
    var a = 1;
    function g(a){
        return a + 1;
    }
    return g;
}
f()(3); // 4
4.arguments对象

函数的实际参数会被保存在一个类数组对象 arguments 对象中,通过索引访问具体的参数:

var a = arguments[i]

arguments的索引从0开始,也有arguments.length属性获取长度。
当我们不知道参数的数量的时候,可以使用arguments.length来获取实际传入参数的数量,再用arguments对象来获取每个参数。
例如:

// 拼接所有参数为一个字符串
// 参数 s 为分隔符
function f( s ){
    var text = "";
    for(var i = 0;i<= arguments.length; i++){
        text += arguments[i] + s ;
    }
    return text;
}

f("--","leo","pingan","robin");
// "----leo--pingan--robin--undefined--"
f("**","leo","pingan","robin");
// "****leo**pingan**robin**undefined**"
5.函数参数

ES6开始,新增两个类型的参数:默认参数剩余参数

5.1默认参数

若函数没有传入参数,则参数默认值为undefined,通常设置参数默认值是这样做的:

// 没有设置默认值
function f(a, b){
    b = b ? b : 1;
    return a * b;
}
f(2,3);  // 6
f(2);    // 2

// 设置默认值
function f(a, b = 1){
    return a * b;
}
f(2,3);  // 6
f(2);    // 2
5.2剩余参数

可以将参数中不确定数量的参数表示成数组,如下:

function f (a, ...b){
    console.log(a, b);
}
f(1,2,3,4); // a => 1 b => [2, 3, 4]
6.箭头函数

函数箭头表达式是ES6新增的函数表达式的语法,也叫胖箭头函数,变化:更简洁的函数和this

更简洁的函数

// 有1个参数
let f = v => v;
// 等同于
let f = function (v){return v};

// 有多个参数
let f = (v, i) => {return v + i};
// 等同于
let f = function (v, i){return v + i};

// 没参数
let f = () => 1;
// 等同于
let f = function (){return 1};

let arr = [1,2,3,4];
arr.map(ele => ele + 1);  // [2, 3, 4, 5]

this

注意这几点:

1. 箭头函数内的`this`总是指向**定义时所在的对象**,而不是调用时。  
2. 箭头函数不能当做**构造函数**,即不能用`new`命令,否则报错。  
3. 箭头函数不存在`arguments`对象,即不能使用,可以使用`rest`参数代替。  
4. 箭头函数不能使用`yield`命令,即不能用作Generator函数。  

一个简单的例子:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++;
  }, 1000);
}
var p = new Person(); // 定时器一直在执行 p的值一直变化
参考资料

1.MDN 函数

本部分内容到这结束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787...
JS小册 js.pingan8787.com

欢迎关注微信公众号【前端自习课】每天早晨,与您一起学习一篇优秀的前端技术博文 .

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100006.html

相关文章

  • 重温基础】21.高阶函数

    摘要:欢迎您的支持系列目录复习资料资料整理个人整理重温基础篇重温基础对象介绍重温基础对象介绍重温基础介绍重温基础相等性判断重温基础闭包重温基础事件本章节复习的是中的高阶函数,可以提高我们的开发效率。 本文是 重温基础 系列文章的第二十一篇。 今日感受:想家。 本人自己整理的【Cute-JavaScript】资料,包含:【ES6/ES7/ES8/ES9】,【JavaScript基础...

    wua_wua2012 评论0 收藏0
  • 重温基础】15.JS对象介绍

    摘要:构造函数通常首字母大写,用于区分普通函数。这种关系常被称为原型链,它解释了为何一个对象会拥有定义在其他对象中的属性和方法。中所有的对象,都有一个属性,指向实例对象的构造函数原型由于是个非标准属性,因此只有和两个浏览器支持,标准方法是。 从这篇文章开始,复习 MDN 中级教程 的内容了,在初级教程中,我和大家分享了一些比较简单基础的知识点,并放在我的 【Cute-JavaScript】系...

    booster 评论0 收藏0
  • 重温基础】11.Map和Set对象

    摘要:本文是重温基础系列文章的第十一篇。返回一个布尔值,表示该值是否为的成员。使用回调函数遍历每个成员。与数组相同,对每个成员执行操作,且无返回值。 本文是 重温基础 系列文章的第十一篇。 今日感受:注意身体,生病花钱又难受。 系列目录: 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理) 【重温基础】1.语法和数据类型 【重温基础】2.流程控制和错误处理 【重温基础】3....

    meteor199 评论0 收藏0
  • 重温基础】14.元编程

    摘要:本文是重温基础系列文章的第十四篇。元,是指程序本身。有理解不到位,还请指点,具体详细的介绍,可以查看维基百科元编程。拦截,返回一个布尔值。 本文是 重温基础 系列文章的第十四篇。 这是第一个基础系列的最后一篇,后面会开始复习一些中级的知识了,欢迎持续关注呀! 接下来会统一整理到我的【Cute-JavaScript】的JavaScript基础系列中。 今日感受:独乐乐不如众乐乐...

    cc17 评论0 收藏0
  • 重温基础】10.数组

    摘要:本文是重温基础系列文章的第十篇。返回一个由回调函数的返回值组成的新数组。返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。回调函数接收三个参数,当前值当前位置和原数组。 本文是 重温基础 系列文章的第十篇。 今日感受:平安夜,多棒。 系列目录: 【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理) 【重温基础】1.语法和数据类型 【重温基础】2.流程控制和错误...

    DangoSky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<