ES6 函数的扩展

2019-03-13  本文已影响0人  灬劣徒
image.png

函数参数的默认值

ES6允许为函数的参数设置默认值,即直接写在参数定义的后面

function log(x,y = 'world') {
  console.log(x,y)      
}   
log('hello')  //'hello'                  

//参数变量是 默认声明的,所以不能用let或const 再次声明
function foo(x = 5) {
  let x = 1;
  const x = 2;  
}

//函数参数默认值是惰性求值的
let x = 100;
function foo(p = x + 1){
  console.log(p) 
}
foo(); //101
x = 101;
foo() //102

函数参数默认值与解构赋值默认值结合使用

function foo({x,y = 5}) {
  console.log(x,y)
}
foo({}) //undefined,5
foo({x:1}) //1,5
foo({x:1,y:2}) //1,2
foo() //TypeError:cannot read property 'x' of undefined;

以上代码只使用对象的解构赋值的默认值,并没有使用函数参数的默认值,下面是结合使用的列子:

function foo({x,y = 5} = {}) {
  console.log(x,y) //undefined,5
}
//不设置函数参数默认值,会报错
function fetch(url,{body:'',method:'GET',headers = {} } ) {
  console.log(method)
}
fetch('http:example.com') //报错

//设置参数默认值,不会报错
function(url,{body:'',method:'GET',headers = {} } = {} ) {
  console.log(method)
}
fetch('http:example')  //GET

老铁,''是时候表演真正的技术了'',说说以下两种写法的区别,顺便再做几个练习题吧

//写法一:设置了对象解构赋值的默认值,但是函数参数的默认值是个空对象
function m1({x = 0,y = 0} = {}) {
  return [x,y] //
}

//写法二:设置了函数参数的默认值是一个有属性的对象,但是没有设置对象解构赋值的默认值
function m2({x,y} = {x:0,y:0}) {
  return [x,y]
}
注意:({x,y} = {x:0,y:0}) 不能写成({x,y} = {x= 0,y = 0})

m1(); // [0,0]
m2(); // [0,0]
m1({}); //[0,0]
m2({}); //[undefined,undefined]
m1({x:3,y:8}); //[3,8]
m2{{x:3,y:8}}; //[3,8]
m1({x:3}) //[3,0]
m2({x:3}) //[3,undefined]
m1({z:3}); //[0,0]
m2({z:3}); //[undefined.undefined]

参数默认值的位置

通常定义默认值的参数,都会在参数值的尾部(就这样吧~稍作了解就得了)

function foo(x,y = 5,z) {
  return [x,y,z]
}
foo(); //[undefined,5,undefined]
foo(1); //[1,5,undefined]
foo(1, ,2); // 报错
foo(1,undefined,2) //[1,5,2]
foo(1,null,2) //[1,null,2]

函数的length属性(该函数预期传入的参数个数,如果设置默认值,就不包括在这个里面了)

函数参数设置默认值以后,函数的length属性,返回没有设置默认值的参数个数

(function f1(x){}).length  // 1
(function f2(x = 1){}).length // 0
(function f3(x,y,z = 5){}).length // 2
(function f4(x,y = 1,z){}).length // 1
(function f5(x =1,y,z){}).length // 0
(function f6(...args){}).length // 0

作用域(感觉这章很重要,但是有点看不懂啊)

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


rest参数

ES6引入rest参数,用来获取函数的多余参数(...变量名).这样就不用arguments

//rest参数代替arguments对象
function args(){                                                                     
  return Array.prototype.slice.call(arguments).sort();     =>     const args = (...numbers) => numbers.sort();                      
}                                                                                      

function push(array,...items) {
  items.forEach(function(item) {
    array.push(item);
    console.log(item)
  })
}
var a  = [];
push(a,1,2,3);

请注意两个坑: ① rest参数只能在参数的最后 ②函数的length属性不包括rest参数

严格模式

ES5可以在函数内部使用严格模式'user strict'
ES6做出了一点修改,即只要函数参数使用了默认值,解构赋值,或者扩展运算符(rest参数),函数内部就不能显示设定为严格模式

name属性(函数的name属性,返回该函数的函数名)

在ES5,如果一个匿名函数赋值给一个变量,这个函数的name属性返回的是一个空字符串
在ES6,会返回实际的函数名

const foo = function baz(){}
//ES5
foo.name // baz
//ES6
foo.name // baz

//Function的实例对象是anonymous
(new Function).name // anonymous

//bind返回的函数,name属性值会加上bound前缀
function foo() {}
foo.bind({}).name // bound foo
(function() {}).bind({}).name // bound

箭头函数(来了,传说中的箭头函数~)

//如果箭头函数没有参数or需要多个参数,就使用一个圆括号代表参数部分
//如果只有一个参数,可以省略圆括号
let f = () => { 5 }
let sum = (num1,num2) => {return num1 + num2 }
let temp = id => console.log(id)

//如果函数体中的语句多于一条,就得使用大括号(return关键词单独算是一条语句)
let sum = (num1,num2) => { return num1 + num2}; 

//如果函数体**直接**返回一个对象,必须用圆括号包裹这个对象,因为大括号被解读为一个代码块
let getObj = id => {id:id,name:'JC_cooper'} // 报错
let getObj = id => ({id:id,name:'JC_cooper'})
上一篇下一篇

猜你喜欢

热点阅读