ES6-函数的扩展

ES6对函数的扩展总要将两件事,一个是函数的参数,一个是箭头函数,这两点扩展为JS代码编写来说是两个大大的惊喜,未来我们会经常用到这两个新特性。

ES6中函数的参数

与之前的版本不同,ES6中函数的参数有几个值得注意的新特性.

1、ES6允许为函数的参数设置默认值

从前JS的函数不能像其他编程语言那样设置默认值,通常在写函数时首先要对参数进行判断,如果没传参数,给定一个默认值。

function fun1(param)
{
  var param = param || "empty";
  return param;
}
console.log(fun1(1),fun1(),fun1(undefined),fun1(0),fun1(""),fun1(false),fun1(null)) 
//1 "empty" "empty" "empty" "empty" "empty" "empty"

PS:||符号运算规则
如果“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。
如果“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值。

这样写有个问题,那就是“||”运算时,会进行类型转换,导致传入空字符串、0、false、undefined和null时和没传递参数是一样的,而实际上从语义上来说,只有不传参,或传入undefined才算没有传参,如果要避免这个情况还要进行其他的判断。
ES6加入了能够为参数设置默认值,这样不仅在书写上更加方便,也避免了上述出现的问题

function fun2(param="empty")
{
  return param;
}
console.log(fun2(1),fun2(),fun2(undefined),fun2(0),fun2(""),fun2(false),fun2(null)) //1 "empty" "empty" 0 "" false null

实际上这种写法是利用了函数的arguments对象,编译成ES5的语法是这样的:

function fun2() {
  var param = arguments.length <= 0 || arguments[0] === undefined ? "empty" : arguments[0];
  return param;
}

函数有多个参数时,如果只给部分的参数设置默认值,那么有默认值的参数要放到最后。如下面的例子中,因为a,b有默认值,如果希望只能c传值的话,第一种写法是错误的。

  function fun1(a=1,b=2,c) {
    console.log(a,b,c)
  }
  fun1(3);	//3 2 undefined
  function fun2(c,a=1,b=2) {
    console.log(a,b,c)
  }
  fun2(3);	//1 2 3
2、参数默认值可以与解构赋值的默认值,结合起来使用。

ES6 声明与表达式中讲解构赋值的作用时,说过解构赋值可以定义函数参数并设置默认值,有这样一个例子

function fun({name,age,gender='male'}){
  console.log(`姓名:${name},年龄:${age},性别:${gender}`);
}
fun({name:"Lily",age:"18",weight:"50"});  //姓名:Lily,年龄:18,性别:male

函数fun的参数是一个对象,这个例子中如果调用fun不传递参数的话,会报错(Uncaught TypeError),这是因为函数中参数的属性设置了默认值,但是没有给参数设置默认值

function fun({name,age,gender='male'}={}){
  console.log(`姓名:${name},年龄:${age},性别:${gender}`);
}
fun();	//姓名:undefined,年龄:undefined,性别:male
3、剩余参数的使用

在介绍解构赋值的时候,说到过Rest运算符和扩展运算符( … ),可以去温习一下。
下面的例子中fun的形参…rest表示一个参数序列,rest表示一个数组,他们正好是相反的。
如下,在调用fun(…[1,2,3])时,看起来像是传递了一个数组,其实不是的,扩展运算符( … )将一个数组转为用逗号分隔的参数序列,fun(…[1,2,3])和fun(1,2,3)是一样的。

function fun(...rest)
{
  console.log(rest,...rest);
}
arr=[1,2,3];
fun(...arr);  //[1, 2, 3]   1 2 3

再看一个例子,本例中…rest是fun函数除第一个参数以外的所有参数的序列化。…rest在不确定参数数量时非常有用

function fun(first,...rest)
{
  console.log(first,rest);
}
fun(1,2,3);		//1 [2,3]

箭头函数

ES6标准新增了一种新的函数:Arrow Function(箭头函数)
过去定义一个函数可以使用函数声明或者函数表达式的方式,语法是:
function 函数名(){}
var 函数名 = function(){}

箭头函数的写法:
  • function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。
  • 函数参数只有一个,括号可以省略;但是没有参数时,括号不可以省略。
  • 箭头函数的函数体重如果只包含一个表达式,省略掉了{ … }和return,但是如果这个表达式是一个对象的话要用小括号包裹。
function fun1(x,y){
	return x+y
}
var fun2=function(x,y){
  return x+y;
}
//箭头函数写法
let fun3=(x,y)=>x+y;

//只有一个参数,省略小括号,函数体只有一个表达式,省略{}和return,只有一个参数
x=>x*x
//没有参数,不能省略()
var fun=()=>console.log('没有参数');

将x=>x*x编译成ES5,代码是这样的:

"use strict";

(function (x) {
  return x * x;
});
匿名函数和箭头函数的区别

箭头函数相当于匿名函数,并且简化了这种函数定义,但是箭头函数和匿名函数函数有一定的区别的:

  • 箭头函数中没有自己的this,箭头函数内的this就是箭头函数外的那个this
  • 箭头函数中没有arguments对象,箭头函数内的arguments就是箭头函数外的那个arguments

下面的代码中希望如果对象p的国籍是中国的话,调用它的方法getfullName时,返回他的姓名而不是名姓。

var p={
  firstName:"三",
  lastName:"张",
  nationality:"Chinese",
  getFullName:function () {
    console.log('getFullName()中:\n',this,arguments);
    function connect() {
      console.log('connect()中:\n',this,arguments);
      if(this.nationality==="Chinese") return this.lastName+this.firstName
    }
    return connect();
  }
}
//随便传入2个参数用于区分arguments对象
console.log(p.getFullName(1,2));

在这里插入图片描述
这个例子中,并没有的得到我们要的结果,并且函数getFullName和connect中都有自己的this和arguments。

还记得在函数入门篇关于函数的调用,有这样的说法吗?
1、函数调用模式: 函数名();
调用函数实际上就是调用某个对象的方法,如果函数名前没有对象,那么意味着调用的是window对象的方法,这时的this指向window
2、方法调用模式: 对象.函数名();
this:谁调用就指向谁
在上面的例子中getFullName()作为对象p的方法调用,其内部的this就是p,但是方法中的connect是作为函数调用的,非严谨模式里面的this指向window,严谨模式this为undefined。

下面把代码稍微改造一下,在执行getFullName方法时,将此时的this赋值给一个变量_this,之后获取_this的属性来得到想要的结果

var p={
    firstName:"三",
    lastName:"张",
    nationality:"Chinese",
    getFullName:function () {
      var _this=this;
      console.log('getFullName()中:\n',this,arguments);
      function connect() {
        console.log('connect()中:\n',_this,arguments);
        if(_this.nationality==="Chinese") return _this.lastName+_this.firstName
      }
      return connect();
    }
  }
console.log(p.getFullName(1,2));  //张三

现在改用箭头函数来写

var p={
  firstName:"三",
  lastName:"张",
  nationality:"Chinese",
  getFullName:function () {
    console.log('getFullName()中:\n',this,arguments);
    let connect=()=> {
      console.log('connect()中:\n',this,arguments);
      if(this.nationality==="Chinese") return this.lastName+this.firstName
    }
    return connect();
  }
}
console.log(p.getFullName(1,2));

在这里插入图片描述
为什么会这样呢?实际上把上面的代码编译成ES5,就非常清楚了

var p = {
  firstName: "三",
  lastName: "张",
  nationality: "Chinese",
  getFullName: function getFullName() {
    var _this = this,
        _arguments = arguments;

    console.log('getFullName()中:\n', this, arguments);
    var connect = function connect() {
      console.log('connect()中:\n', _this, _arguments);
      if (_this.nationality === "Chinese") return _this.lastName + _this.firstName;
    };
    return connect();
  }
};

console.log(p.getFullName(1, 2));
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值