函数参数的默认值
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'})
-
箭头函数有4个注意点:
1.函数中的this,就是定义时所在的对象,而不是使用时所在的对象,说白了就是,this从"动态"变成"静态"
2.箭头函数不能用作构造函数,也就是说不能使用new命令,否则会报错
3.不能使用arguments对象,请使用rest参数代替
4.不可以使用yield命令,因此不可以使用Generator函数
网友评论