博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【重温基础】4.函数
阅读量:6940 次
发布时间:2019-06-27

本文共 4100 字,大约阅读时间需要 13 分钟。

本文是 重温基础 系列文章的第四篇。

今日感受:常怀感恩之心,对人对己。

系列目录:

本章节复习的是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 scopevar a = 1, b = 2;function f (){    return a + b;}f(); // 3function 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); // 11var 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);  // 6f(2);    // 2// 设置默认值function f(a, b = 1){    return a * b;}f(2,3);  // 6f(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的值一直变化

参考资料


本部分内容到这结束

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

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

转载地址:http://yksnl.baihongyu.com/

你可能感兴趣的文章
GSoap根据filename读取图片byte
查看>>
VC下利用Picture控件实现png图片按钮(鼠标初始、按下、松开、获得焦点四种状态)...
查看>>
设计模式-原型模式
查看>>
143. Reorder List
查看>>
Material Design(三)--UI控件之CardView
查看>>
91. Reverse Linked List 反转链表
查看>>
#include<cmath>
查看>>
SimpleAdapter不能自动更新 求解释
查看>>
正则表达式
查看>>
Delphi中TList类应用
查看>>
DLL技术应用03 - 零基础入门学习Delphi46
查看>>
壳的执行过程
查看>>
多维数组元素的地址
查看>>
动态内存管理 - C++快速入门33
查看>>
iOS 动画篇(一) Core Animation
查看>>
css背景雪碧图等
查看>>
odoo 之报date<form string=''product lc''> 错误
查看>>
leetcode34. Find First and Last Position of Element in Sorted Array
查看>>
62. Unique Paths(矩阵的总路径数)
查看>>
【巧妙的模拟】【UVA 10881】 - Piotr's Ants/Piotr的蚂蚁
查看>>