默认参数
解决问题:
必填项不填报错
有些参数没有传参时给默认值
ES6 之前,不能直接为函数的参数指定默认值,ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面
//es5
function ajax(url,method,dataType) {
if(typeof url === 'undefined') throw Error('url不能为空');
method=method?method:'GET';
}
//es6
function ajax(url=Error('url不能为空'),method='GET',dataType='json') {
console.log(url);
console.log(method);
console.log(dataType);
}
ajax('/user')
/*
/user
GET
json
*/
//上面的写法编译为es5
function ajax() {
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Error('url不能为空');
var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'GET';
var dataType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'json';
console.log(url);
console.log(method);
console.log(dataType);
}
1、参数变量是默认声明的,所以不能用let或const再次声明
下面代码中,参数变量x是默认声明的,在函数体中,不能用let或const再次声明,否则会报错。
function foo(x = 5) {
let x = 1; // 报错
const x = 2; // 报错
}
2、使用参数默认值时,函数不能有同名参数
// 不报错
function foo(x, x, y) {
// ...
}
// 报错
function foo(x, x, y = 1) {
// ...
}
3、参数默认值不是传值的,而是每次都重新计算默认值表达式的值
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
解构赋值的运用
基础版:不传会报错
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);
}
foo() // undefined 5
完整版的两种写法:(一般用写法一)
写法一
函数参数的默认值是空对象
,但是设置了对象解构赋值的默认值
;
写法二
函数参数的默认值是一个有具体属性的对象
,但是没有设置对象解构赋值的默认值
。
// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]
// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]
// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]
// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]
m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
非尾部的参数设置默认值,这个参数是没法省略的
有默认值的参数都不是尾参数。这时,无法只省略该参数,而不省略它后面的参数,除非
在不想传参的参数的对应位置显式输入undefined(传null不行)
。
参数对应undefined,会触发默认值,null不会触发默认值
// 例一
function f(x = 1, y) {
return [x, y];
}
f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 报错
f(undefined, 1) // [1, 1]
// 例二
function f(x, y = 5, z) {
return [x, y, z];
}
f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 报错
f(1, undefined, 2) // [1, 5, 2]
function foo(x = 5, y = 6) {
console.log(x, y);
}
foo(undefined, null)
// 5 null
剩余运算符运用
//arguments利用 剩余运算符
function fn(context,...arg){
//获取传递值中的第一个和剩下的
console.log(context)
console.log(arg) //arg 是数组 ,而arguments是类数组
}
var obj={name:'aaa'}
fn(obj,10,20)
展开运算符运用
let arr=[12,23,34];
let fn=function(a,b,c){
console.log(a,b,c)
}
//fn(arr) //arr undefined undefined
fn(...arr) //=>fn(12,23,34) => 打印 12 23 34
箭头函数
1、箭头函数中没有arguments,可以使用剩余运算符(...arg)代替而且arg是一个数组
箭头函数中没有执行主体,就是没有this
2、在箭头函数中,this固定的,不会变的
3、函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
4、在箭头函数中的this都是直接找上下文中的this来使用(上级作用域中的this,而非上级代码块{}、或者说不是上级json对象)
箭头函数中的this跟执行的时候前面有没有点没关系了,因为他没有执行主体,
在箭头函数中的this都是直接找上下文中的this来使用(上级作用域中的this,而非上级代码块{}、或者说不是上级json对象)
5、不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
6、不可以使用yield命令,因此箭头函数不能用作 Generator 函数
let fn=(x,y)=>{
}
fn(10,20)
7、只有一个形参可以省略小括号
let fn= x =>{
}
fn(10)
8、如果函数体中只有一句操作,并且是return 的,我们可以省略大括号和return
箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
let fn= function(x,y){
return x+y;
}
fn(10,20)
let fn=(x,y)=>x+y;
console.log(fn(10,20)) //30
let fn=(x=0,y=0)=>x+y; //给形参设置默认值
console.log(fn(10,20)) //30
let fn= x => y => x+y
/*
相当于 let fn= x =>( y => x+y)
*/
let fn=function(x){
return function(y){
return x+y;
}
}
let fn =(...arg)=>{
//arg就是全部参数,并且arg为数组
}
fn(10,20,30)
9、如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
//在箭头函数中的this都是直接找上下文中的this来使用(上级作用域中的this,而非上级代码块{}、或者说不是上级json对象)
let obj={
name:'aaa',
fn:()=>{
console.log(this.name)
}
}
let obj2={
name:'bbb',
fn:obj.fn
}
obj.fn(); //undefined
obj2.fn(); //undefined
例题
例1、让obj.fn的this变为window
let obj={
fn:(function(){
//this:window
return function(){
console.log(this)
}
})()
}
obj.fn(); //this:obj
//1、
obj.fn.call(window)
//2、
let obj={
fn:(function(){
//this:window
var _this=this;
return function(){
console.log(_this)
}
})()
}
//3、
let obj={
fn:(function(){
//this:window
return ()=>{
//this:window
console.log(this)
}
})()
}
obj.fn(); //this:window
例2、
考点:自执行函数中的this 为window
let obj={
name:'aaa',
fn:function(){
var self=this;
console.log(this.name);
console.log(self.name);
~function() {
console.log(this.name)
console.log(self.name)
}()
}
}
obj.fn()
//aaa
//aaa
//undefined
//aaa
考点:箭头函数中的this是定义时所在作用域的this
let obj={
name:'aaa',
fn:function(){
var self=this;
console.log(this.name);
console.log(self.name);
(()=> {
console.log(this.name)
console.log(self.name)
})()
}
}
obj.fn()
//aaa
//aaa
//aaa
//aaa
考点:自执行函数中的this 为window;箭头函数中的this是定义时所在作用域的this,let定义的与window无关
let name='全局';
let obj={
name:'aaa',
fn:(function(){
var self=this;
console.log(this.name);
console.log(self.name);
return ()=> {
console.log(this.name)
console.log(self.name)
}
})()
}
obj.fn()
//undefined
//undefined
//undefined
//undefined
考点:自执行函数中的this 为window;箭头函数中的this是定义时所在作用域的this
let obj={
name:'aaa',
fn:(function(){
var self=this;
console.log(this.name);
console.log(self.name);
return function(){
console.log(this.name)
console.log(self.name)
}
})()
}
obj.fn()
//undefined
//undefined
//aaa
//undefined
以下情况不能使用箭头函数:
1、定义函数的方法,且该方法内部包括this
const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}