es6判断空函数_ES6函数的扩展

函数参数的默认值

在ES6之前,不能直接为函数指定默认值。

eg:

function funcEs5(test){test = test || '默认值'console.log(test)}funcEs5() // 打印结果默认值,因为没有给值 // 当给值时function funcEs5(test){test = test || '默认值'console.log(test)}funcEs5('给定值') // 打印结果给定值

但是这样的话就会产生一个问题,JS的逻辑或运算符只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值,只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。而且它的true和false是存在隐式转化的,也就是说,如果你想在ES5中给参数传 0, false, 空字符串等可以隐私转换为false的参数,是会凉掉的。。

EG:

function funcEs5(count, bool, str){count = arguments[0] || '默认数字'bool = arguments[1] || '给它一个true'str = arguments[2] || '默认字符串'console.log(count, bool, str)}funcEs5(0, false, "")// 打印结果:默认数字 给它一个true 默认字符串

当然啦,肯定有解决的办法的啦

判断一下它是否为undefined,如果是,说明该参数没有赋值:

function funcEs5(count, bool, str){arguments[0] === undefined && '给它默认数字'arguments[1] === undefined && '给它一个true'arguments[2] === undefined && '默认字符串'console.log(count, bool, str)}funcEs5(0, false, "") // 打印结果:0 false ""

好啦,现在开始说ES6的允许为函数的参数设置默认值,大家把前面的忘了吧

非常简单,直接写在括号中的参数后面即可

function funcES6(test = '有本事你就给我赋值') {console.log(test) // 打印结果:有本事你就给我赋值}funcES6()

如果你给该参数赋值,则默认值不会生效,否则取默认值

function funcES6(test = '有本事你就给我赋值') {console.log(test) // 打印结果:我要赋值啦}funcES6('我要赋值啦')

与解构赋值默认值结合使用

关于解构赋值ES6对象的扩展(上)ES6对象的扩展(下)

先来看看使用对象的解构赋值默认值吧

let obj = {name: '我不是默认姓名',age: undefined}funcES6(obj)function funcES6({ name, age = '18' }) {console.log(name, age)}// 打印结果: 我不是默认姓名 18

我给age一个undefined,相当于age属性没有传值:

let obj = {name: '我不是默认姓名'}funcES6(obj)function funcES6({ name, age = '18' }) {console.log(name, age)} // 当该属性没有传值时,获取到的是undefined

同时,这种写法里的参数拿到的是传入对象的name属性和age属性,其它属性一律过滤,假设你ajax没有封装的话,{ data } => {} 一般可以直接拿到后端返回的数据(axios是这样)

当对象的解构赋值配合函数的默认值时

在上个例子中,我那种写法其实非常不严谨很low的一种写法,因为当没有传入参数时,它是会报类型错误的:

let obj = {name: '我不是默认姓名'}funcES6()function funcES6({name, age = '18'}) {console.log(name, age)} // Uncaught TypeError: Cannot match against 'undefined' or 'null'.

这是因为你没传的话,它就是undefined,它不是对象,它无法解构,所以一般,我们在遇到这种是,应该考虑到如果没有传入参数以及传入参数之后我们需要那些属性,实现方式:

funcES6()function funcES6({name, age = '18'} = {}) {console.log(name, age)} // undefined "18"

当我们没有传入参数时,我们使用ES6函数的扩展给它指定一个默认值,当传入时也可以用解构赋值来取到需要用到的属性名!

高逼格用法:

function fetch(url, { body = '', method = 'POST', headers = {} } = {}) {console.log(method);}fetch('http://es6.ruanyifeng.com/#docs/function') // 打印结果:POST

这种写法意思就是说,当你没有传递第二个参数时,先执行等号右边的(给它一个默认值),然后执行等号左边的对象的解构赋值(左边的是对象的解构赋值中给一个默认值),其实跟普通赋值一样,先执行等号右边,然后再是左边。

深入理解:

// 写法一(函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;)function f1({x = 0, y = 0} = {}) {console.log(x, y)}// 写法二(函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。)function f2({x, y} = { x: 0, y: 0 }) {console.log(x, y)}

当我们打印它们在不同情况下得到的结果时:

函数没有参数的情况

f1() // 0 0 f2() // 0 0

x 和 y 都有值的情况

f1(1, 2) // 1, 2

f2(1, 2) // 1, 2

x 有值,y 无值的情况(重点)

f1({x: 1}) // 1, 0f2({x: 1}) // 1, undefined

为什么会出现这种情况呢,这是因为,当我门没有给函数传参时是取默认值,当有参数时,则会覆盖默认值,上面传了单个参数之后,下面其实是变成这样:

// 写法一(函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;)function f1({x = 0, y = 0} = { x: 1 }) {console.log(x, y)}// 写法二(函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。)function f2({x, y} = { x: 1 }) {console.log(x, y)}

当我传入一个参数时,传入的参数会覆盖等号右边的函数默认值,这样的话就会导致函数2被覆盖掉,而函数1则不同,因为js是先执行等号右边的,然后回过头来再执行等号左边的,当对象{x:1}覆盖掉函数1的空对象之后,它会回过来去执行等号左边的对象的解构赋值,然后发现y没有,而对象的解构赋值中y=0!!!

函数的作用域

当一个函数中的参数设置了默认值之后,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。

var x = 1;

function f(x, y = x) {

console.log(y);

}

f(2) // 2

上面代码中,参数y的默认值等于变量x。调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。

此段后续请阅读阮一峰大佬的:http://es6.ruanyifeng.com/#docs/function,

我能力有限,太菜了无法清晰的表达出来

rest 参数(argument)

跟对象的扩展运算符,数组的扩展运算符类似,函数也有属于它自己的扩展运算符(先这么认为吧,反正都是三个点)

4fb7fc690ad98d84b3f4b147de660a19.png

大家可以先把它当arguments(实参列表),不过这样是错的,因为...arg接收的是剩余参数,其次不同于arguments,它就是一个真正的数组,它有数组的所有方法!

建议大家以后都用...arg来代替arguments,因为ES6的箭头函数中,是没有arguments实参列表存在的!

e45cb390c0256cee426057a8c0c28fa2.png

在以往如鱼得水的arguments在ES6中死的很干脆,大家都知道,语法是向前发展的,w3c敢这么玩肯定是有它的道理的!没错,函数扩展运算符完美干掉arguments!

23062d68727dd86c7c3aeb4229b74519.png

老少通吃,不管是ES6,还是ES5,它都可以完美兼容!

arguments能做的它能做,arguments不能做的它也能做!

嗯,虽然它很厉害,但是大家要记下它是剩余参数列表,而不是全部参数列表(形参只写它一个,那它就是)

73befe3a43ae1cd5d134fb408edb1619.png

箭头函数

ES6 允许使用“箭头”(=>)定义函数。(它不会改变this指向,建议大家在setTimeout()和setInterval()使用箭头函数)

b585df78dbcc9ef982c1a14d376cfe85.png

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

718d5f1712d1f8135042e498c8ccfabe.png

如果箭头函数的代码块部分只有一条语句,则可以省略 return

8be7da5ccdfdc007012e01667555d0ff.png

不过返回的是对象的话,就不能这么写了,因为对象和块级作用域都是包个大括号表示,我们有两种方式来处理这种:

// 方式一let obj = {a: 999}let funcES6 = () => obj// 方式二let funcES6 = () => ({a: 999}) // 推荐方式二

如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。

535ca152c56019bb6201d2f75e13aa26.png

void 操作符指定要计算一个表达式但是不返回值。(执行函数代码,但是有没有return都是undefined)

箭头函数可以与变量解构结合使用。

c1e3ceb7b675f1c4387703173b61006d.png

使用注意事项:

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象(不改变this指向)。
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替(...arg)。

关于第一点,划重点!!!!

箭头函数的this指向,在函数生成的那一刻,已经绑定到定义时所在的作用域中,而不是跟普通函数一般,绑定在执行时所在的作用域!

eg: 1,我们先搓出来一个局部作用域,此时内部的this指向指向的是对象obj;

c1405edcf932ec85c0da7eee78bd92a0.png

es5之前的函数是谁调用它,this就指向谁,它的this作用域就是谁,也就说是,它的作用域是在函数执行之后才生成的,而es6的箭头函数作用域在函数生成之后便会随之生成!

999e87a1f87822041654f9a7ad9b02d9.png

如图所示,当这两个函数都没有被人调用时,默认为全局调用,所以es5的指向window,而es6的指向当前作用域,它的this指向没有被改变。

重点参考阮一峰大大的ES6标准入门,感兴趣的大佬可以看看(比我写的好太多啦):http://es6.ruanyifeng.com/#docs/function

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值