当前位置 : 主页 > 网络编程 > PHP >

【JS】123-重温基础:函数

来源:互联网 收集:自由互联 发布时间:2023-09-06
本文是重温基础系列文章的第四篇。 今日感受:常怀感恩之心,对人对己。 本章节复习的是JS中的基础组件之一,函数,用来复用特定执行逻辑。 1.定义函数 定义函数有两种方法:函

【JS】123-重温基础:函数_内部函数

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

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

1.定义函数

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

1.1 函数声明

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

  1. ​​function f (a){​​
  2. ​​    return a + 1;​​
  3. ​​}​​

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

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

  1. ​​var leo = {​​
  2. ​​    age:20​​
  3. ​​}​​
  4. ​​function f(obj){​​
  5. ​​    obj.age = 15;​​
  6. ​​    obj.name = 'leo';​​
  7. ​​}​​
  8. ​​f(leo);​​
  9. ​​console.log(leo); //{age: 15, name: "leo"}​​

1.2函数表达式

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

  1. ​​var f = function (a){​​
  2. ​​    return a + 1;​​
  3. ​​}​​

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

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

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

  1. ​​var f;​​
  2. ​​if(a == 1){​​
  3. ​​    f = function (){​​
  4. ​​        return 'when a == 1';​​
  5. ​​    }​​
  6. ​​}else {​​
  7. ​​    f = function (){​​
  8. ​​        return 'when a != 1';​​
  9. ​​    }​​
  10. ​​}​​

2.函数调用

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

  1. ​​var f = function (){​​
  2. ​​    console.log('ok');​​
  3. ​​}​​
  4. ​​f(); // 'ok'​​

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

  1. ​​function f (n){​​
  2. ​​    if( n==0 || n==1) {​​
  3. ​​        return 1;​​
  4. ​​    }else {​​
  5. ​​        return n * f(n-1);​​
  6. ​​    }​​
  7. ​​}​​
  8. ​​// 三目运算​​
  9. ​​function f (n){​​
  10. ​​    return (n==0 || n==1)?1: n*f(n-1);​​
  11. ​​}​​

3.函数作用域

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

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

  7. ​​function g(){​​
  8. ​​    var a1 = 'leo', b1 = 'pingan';​​
  9. ​​    function hi (){​​
  10. ​​        return a1 + '和' + b1​​
  11. ​​    } ​​
  12. ​​    return hi();​​
  13. ​​}​​
  14. ​​g(); // 'leo和pingan'​​

3.1 闭包

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

  • 内部函数只能在外部函数中访问;
  • 内部函数形成闭包:可以访问外部函数的参数和变量,但外部函数却不能使用这个内部函数的参数和变量;
  1. ​​function f(a) {​​
  2. ​​    function g(b){​​
  3. ​​        return a + b;​​
  4. ​​    }​​
  5. ​​    return g;​​
  6. ​​}​​
  7. ​​var a1 = f(5);  // ƒ g(b){ return a + b; }​​
  8. ​​var a2 = a1(6); // 11​​
  9. ​​var a3 = f(5)(6); // 11​​

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

  1. ​​var f = function (name){​​
  2. ​​    var age ;​​
  3. ​​    return {​​
  4. ​​        setName : function (newName){​​
  5. ​​            name = newName;​​
  6. ​​        },​​

  7. ​​        getName : function (){​​
  8. ​​            return name;​​
  9. ​​        },​​

  10. ​​        getAge : function (){​​
  11. ​​            return age;​​
  12. ​​        },​​
  13. ​​        setAge : function (newAge){​​
  14. ​​            age = newAge;​​
  15. ​​        }​​
  16. ​​    }​​
  17. ​​}​​

  18. ​​var leo = f('leo');​​
  19. ​​leo.setName('pingan');​​
  20. ​​leo.setAge(20);​​
  21. ​​leo.getName();     // 'pingan'​​
  22. ​​leo.getAge();      // 20​​

3.2命名冲突

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

  1. ​​function f(){​​
  2. ​​    var a = 1;​​
  3. ​​    function g(a){​​
  4. ​​        return a + 1;​​
  5. ​​    }​​
  6. ​​    return g;​​
  7. ​​}​​
  8. ​​f()(3); // 4​​

4.arguments对象

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

  1. ​​var a = arguments[i]​​

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

  1. ​​// 拼接所有参数为一个字符串​​
  2. ​​// 参数 s 为分隔符​​
  3. ​​function f( s ){​​
  4. ​​    var text = '';​​
  5. ​​    for(var i = 0;i<= arguments.length; i++){​​
  6. ​​        text += arguments[i] + s ;​​
  7. ​​    }​​
  8. ​​    return text;​​
  9. ​​}​​

  10. ​​f('--','leo','pingan','robin');​​
  11. ​​// "----leo--pingan--robin--undefined--"​​
  12. ​​f('**','leo','pingan','robin');​​
  13. ​​// "****leo**pingan**robin**undefined**"​​

5.函数参数

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

5.1默认参数

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

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

  8. ​​// 设置默认值​​
  9. ​​function f(a, b = 1){​​
  10. ​​    return a * b;​​
  11. ​​}​​
  12. ​​f(2,3);  // 6​​
  13. ​​f(2);    // 2​​

5.2剩余参数

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

  1. ​​function f (a, ...b){​​
  2. ​​    console.log(a, b);​​
  3. ​​}​​
  4. ​​f(1,2,3,4); // a => 1 b => [2, 3, 4]​​

6.箭头函数

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

  • 更简洁的函数
  1. ​​// 有1个参数​​
  2. ​​let f = v => v;​​
  3. ​​// 等同于​​
  4. ​​let f = function (v){return v};​​

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

  9. ​​// 没参数​​
  10. ​​let f = () => 1;​​
  11. ​​// 等同于​​
  12. ​​let f = function (){return 1};​​

  13. ​​let arr = [1,2,3,4];​​
  14. ​​arr.map(ele => ele + 1);  // [2, 3, 4, 5]​​
  • this 注意这几点:
  1. 箭头函数内的 ​​this​​总是指向定义时所在的对象,而不是调用时。
  2. 箭头函数不能当做构造函数,即不能用 ​​new​​命令,否则报错。
  3. 箭头函数不存在 ​​arguments​​对象,即不能使用,可以使用 ​​rest​​参数代替。
  4. 箭头函数不能使用 ​​yield​​命令,即不能用作Generator函数。

一个简单的例子:

  1. ​​function Person(){​​
  2. ​​  this.age = 0;​​

  3. ​​  setInterval(() => {​​
  4. ​​    this.age++;​​
  5. ​​  }, 1000);​​
  6. ​​}​​
  7. ​​var p = new Person(); // 定时器一直在执行 p的值一直变化​​

参考资料

1.MDN 函数


【JS】123-重温基础:函数_作用域_02



上一篇:导航网站源码|网址导航源码PHP带手机版
下一篇:没有了
网友评论