ES6 函数的扩展

3 篇文章 0 订阅

1函数参数的默认值

1.1写法

在es6之前,不能够给函数的参数设置默认值,但如果我们需要在没有给某个参数赋值的时候为其设定一个默认的值,一般可以这样写:

function log(x, y) {
    y = y || 'world'    // 在调用函数时候,当没有给参数y赋值的时候让y='world'
    console.log(x, y )
}
// 三种情况的调用
log('hello') // hello world 没有给参数y赋值,所以打印出y值为默认值world
log('hello', 'china') // hello china 给参数y赋值china,所以打印出y值为china
log('hello', '') // hello world 给参数y赋值空字符串,但在||运算符中‘’会被解析为对应的布尔值false,所以打印出y值为默认值world

三种调用结果的分析

  1. 没有给参数y赋值,所以打印出y值为默认值world
  2. 给参数y赋值china,所以打印出y值为china
  3. 给参数y赋值空字符串,但打印出来y值并不是空字符串,而是默认值world,为什么呢?因为在||运算符中空字符串'  '会被当作其对应的布尔值false来处理,所以打印出y值为默认值world,为了避免这个问题,可以先判断一下参数y是否被赋值,如果没有,再让其等于默认值
    if (typeof y === 'undefined') {
         y = 'world'
    }

     

在es6中,允许给函数参数设置默认值,这极大但简化了代码,写法如下:

function log2(x, y='world') {
   console.log(x, y)
}
log2('hello') // hello world 没有给参数y赋值,所以打印出y值为默认值world
log2('hello', 'china') // hello china 给参数y赋值china,所以打印出y值为china
log2('hello', '') // hello world 给参数y赋值空字符串,所以打印出y值为空字符串

1.2参数默认值的位置

通常情况下,定义了默认值的参数应该是函数的尾参数。如果非尾部的参数设置默认值,实际上这个参数也是无法省略的。

1.3函数的length属性

函数的length属性的含义是该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数就不包括这个参数了,所以,设置了默认值的参数不计入length内,包括下面提到的rest参数也不计入length。

1.4参数的作用域

一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域。等到初始化结束,这个参数作用域就会消失。这种语法在不设置参数默认值的时候是不会出现的。

1.4.1当参数的默认值是一个基本类型的数据

// eg1
var x = 1
function foo(x, y=x) {
    console.log(y)
}
foo(2)  // 2


// eg2

var x = 1
function foo(y=x) {
    let x=2
    console.log(y)
}
foo()  // 1
  1.  首先看eg1,在调用函数foo时,发现函数的参数y设置了默认值,此时参数形成了一个单独的作用域。在这个作用域里,存在两个变量,分别是参数x和参数y,所以y=x中的变量x是这个参数作用域里面的x,而不是全局作用域的x,所以y=2。
  2. 再看eg2,在调用函数foo时,发现函数的参数y设置了默认值,此时参数形成了一个单独的作用域。在这个作用域里,存在一个变量y,它的值为一个变量x,但是这个参数作用域内并没有变量x,所以它会去拿全局作用域的x,此时y=1。

1.4.2当参数的默认值是一个函数

var f = 'outer'
function foo2(func = () => f) {
   let f = 'inner'
   console.log(func())
}
foo2()   // outer

在这个例子中,在调用函数foo2时,发现函数的参数func的默认值为一个函数,此时参数形成了一个单独的作用域,而且作为参数func默认值的函数最终返回一个变量f,但是在这个参数作用域里并没有变量f,所以会去拿到全局作用域的f,即outer。

1.5参数默认值的实际应用

在实际开发中经常会遇到这样的情况,我们必须指定函数的某一个参数是必须的,即不能省略的。为了防止这种错误,我们可以利用参数的默认值来做一个提示,给这个参数设置一个默认值(用来描述自己想要做的提示),如果没有传这个必须的参数,将会取默认值。如下为利用参数默认值可以指定某一个参数不得省略,如果省略就抛出一个错误。

function throwIfMissing () {
    throw new Error('Missing parameter')
}
function foo (param1, mustParam = throwIfMissing()) {
    return mustParam
}
foo(1)       //  抛出一个错误Missing parameter
foo(1, 2)    //  没有错误

在上面的这段代码,我们定义了一个函数foo,这个函数foo有两个参数,一个是param1,一个是mustParam,同时为参数mustParam 设置了一个默认值,这个默认值指向一个名叫throwIfMissing的函数。

在用foo(1)调用函数foo时,相当于只给第一个参数param1赋值为1,而第二个参数mustParam为空,此时就会取mustParam的默认值,即throwIfMissing,但是在参数作用域中又没有定义throwIfMissing,所以就会去拿全局作用域的throwIfMissing,执行的结果便是抛出一个错误。

在用foo(1, 2)调用函数foo时,给两个参数都赋值了,因此参数mustParam不会取默认值,所以不会抛出错误。

1.6ES6可设参数默认值究竟有哪些意义(好处)

  • 在某个函数的某个参数没有取到值时,统一给他一个默认值的这种情况下,es6可设置默认值极大了简化了代码;
  • 由于设置默认值的参数都是可以被省略的,所以阅读代码的人可以立刻意识到这个函数的哪些参数是可以省略的,而不用再去查看函数体或文档;
  • 在代码的迭代更新中,有利于代码的优化,即使未来的版本彻底拿掉这个参数,也不会导致之前的代码无法执行。(这条不是很理解哦)

2.rest参数

2.1 写法

rest参数的形式为: ...变量名

小小的补充:在es6中,三个点...有两个名字,一个是扩展运算符,一个是rest参数,那么有什么区别呢?

  • 当用在函数定义时的形参面前,成为rest参数,当函数调用时,用于接收不确定的参数
  • 当与解构赋值组合使用时,称为rest参数,用于接收剩余的值,存储在数组中
  • 当用在字符串或数组前面时成为扩展运算符,将数组或字符串进行拆解。

2.2 arguments对象和rest参数

rest参数的出现在一定程度上代替了arguments对象,而且它的功能更加强大。就此复习一下关于arguments对象的知识,并将arguments对象和rest参数做一个系统的比较

2.2.1 arguments对象

在函数调用的时候,浏览器每次都会传递进两个隐式参数

  • 函数的上下文对象this
  • 封装实参的对象arguments

arguments对象是什么?

function foo () {
     console.log('arguments', arguments)
     console.log('arguments.length', arguments.length)
     console.log('arguments[0]', arguments[0])
     console.log('arguments[1]', arguments[1])
}
foo(1,2,3)

  1. 在js中,函数参数的个数并不是在函数声明时候确定的,而是函数调用时候确定的。arguments对象实际上是所在函数的一个内置类数组对象,每个函数都有一个arguments属性,表示函数的实参集合;
  2. 本质上来讲它是一个对象而不是一个数组,但它和数组很类似,所以通常称为类数组对象(以后看到类数组就可以知道代表的是arguments),它有length属性,表示函数实参的个数,它能够通过arguments[0],arguments[2]这种方式取值,但它不能够调用pop,push等原生数组的方法;
  3. 它不能显式的创建,只有在调用函数时才可以使用;
  4. arguments对象有四个属性:length表示实参的个数;callee表示引用函数自身,写法arguments.callee( );迭代器Symbol;_proto_指向对象的原型。
  5. 在正常模式下,arguments对象可以在运行的时候进行修改,但是在严格模式下不可以修改,如果修改了argument,也不会影响调用函数时原本实参的运行结果。
// 一般模式下修改arguments
function foo(a,b){
     arguments[0] = 10;
     arguments[1] = 20;
     return a + b;
}
console.log(foo(3,6)); //30

// 严格模式下修改arguments
function foo(a,b){
    'use strict';
     arguments[0] = 10;
     arguments[1] = 20;
     return a + b;
}
console.log(foo(3,6)); //9

如果想让arguments对象转变为真正的数组,从而能够使用数组的pop,push等方法,应该怎么做?

Array.prototype.slice.call(arguments)

 2.2.1 rest参数

rest参数是什么?

  •  Rest 参数接受函数的多余参数,组成一个数组,放在形参的最后,形式如下:

    function func(a, b, ...theArgs){
        // ...
    }
  •  rest参数只包括那些没有给出名称的参数,arguments包含所有参数
  •  rest 参数是数组实例,可以直接应用sort, map, forEach, pop等方法
  •  函数的length属性不包括rest参数

3 严格模式

3.1设立严格模式的原因

  • 消除JavaScript语法的一些不合理,不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的JavaScript做好铺垫

"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向。

"use strict";//是进入严格模式的标志(老版本的浏览器会把它当作一行普通字符串,加以忽略。)

3.2 ES6作出的一些改变对设立严格模式有什么影响

从ES5开始,函数内部都可以设定为严格模式。

ES6做了一些修改,规定只要函数参数使用了默认值,解构赋值或扩展运算符,那么函数内部就不能显示设定为严格模式,否则就会报错。

这样规定的原因是:函数内部的严格模式同时适用于函数体和函数参数。但是,函数执行时,先执行函数参数,再执行函数体。这样就有一个不太合理的地方就是,只有从函数体之中才能知道参数是否应该以严格模式执行,但是参数却应该先于函数体执行。所以就很矛盾了。

但有两种方式可以解决这个问题

1.设置全局性的严格模式

'use strict';
function dosomething (a, b = a) {
   // code
}

2.把函数包在一个无参数的立即执行函数里面

const dosomething =  (function () {
    'use strict';
     return function (value = 1) {
         return value
     }
}())

4 箭头函数

箭头函数的写法已经很熟悉了,这里主要总结记录一下关于箭头函数的注意事项。

1.普通函数中,this总是指向函数被调用时所在的对象,但是在箭头函数中,this总是指向函数定义生效时所在的对象;

2.不可以当作构造函数,也就是说不能使用new命令;

3.不可以使用arguments对象,该对象在函数体内不存在。如果要用可以使用rest参数;

4.不可以使用yield命令,因此箭头函数不能用作Generator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值