[扩展]函数默认值对arguments的影响
只能要给函数默认值,该函数自动变量严格模式下的规则:arguments与形参脱离
function test(a,b=1){console.log("arguments:",arguments[0],atguments[1]);console.log("a",a,"b",b);//1,2; a=3;console.log(arguments[0,argumets[1]]);//1,2; console.log(a,b);//1,3}; text(1,2)
[扩展]留意暂时性死区
形参和es6中的let与const声明一样,具有作用域,并且根据参数的声明顺序,存在暂时性死区
function fn(a=b,b){//这样会报错,b是后声明,a前声明,不会变量提升} fn(1,2)
剩余参数
arguments的缺陷
- 如果和形参配合使用,容易出现混乱(argements与形参存在映射关系,但在严格模式下,形参与arguments是脱离的)
- 从语义上,使用arguments获取参数,由于形参缺失,(没有在定义函数时,定义形参。),无法在函数定义上理解函数的真实意图
function sum(...args){//args收集所有的参数,形成一个数组,...是打包}; sum(1);sum(1,2) sum(1,2,3)
剩余参数细节
- 一个函数,仅能出现一个剩余参数
- 一个函数,如果有剩余函数必须是最后一个参数
剩余参数就是用于取代arguments
展开运算符
展开运算符与剩余参数一样,但用途不同。...
用在函数形参时,是用于收集数据打包成一个数组。
console.log(...[1,2,3])//1,2,3
举个栗子:
//克隆一个数组; let arr1 = [1,2,3]; let arr2 = [...arr1]; console.log(arr2);//[1,2,3]; console.log(arr1==arr2);//false,地址不同
对象也可以这样克隆,但是对多维对象来说这是浅克隆(一样对应数组):let obj1 = {name:"es6"};let obj2 = {...obj1}
let obj = {name:"es6",age:{name:"es6"}} let obj1 = {...obj}; console.log(obj1.age === obj.age)//true, //如果要想深克隆可以这样,利用同名属性覆盖; let obj1 = {...obj,age:{...obj.age}};//这样就达成了深克隆了
明确函数的双重用途
Es6提供了一个特殊的API,可以使用该API在函数内部。判断该函数是否使用了new来调用
new.target
//该表达式,得到的是:没有使用new来调用函数,则返回undefined
//如果使用new调用函数,则得到的是new关键字后面的函数本身
//这个函数要用new来调用
function Person(firstName,lastName){
this.firstName = firstName;
this.lastName = lostName;
}
let pr = new Person("java","script");
console.log(pr);//输出实例对象
//用其他方法调用
let pr1 = Person("java","script");
console.log(pr);//undefind
//在es6前,解决这个问题的方法
// function Person(firstName,lastName){
// if(!(this instanceof Person)){//判断this的构造函数是否为Person
// throw new Error("该函数没有使用new来调用")
// }
// this.firstName = firstName;
// this.lastName = lostName;
// }
//但是这个方法有问题,用call,apply就不管用了
let pr2 = Person.call(new Person(),"java","scritp");//强行绑定this
console.log(pr2);//undefined
//使用es6:new.target就可以完美解决
function Person(firstName,lastName){
if(new.target===undefined){
throw new Error("该函数没有使用new来调用");
}
this.firstName = firstName;
this.lastName = lostName;
}
箭头函数
回顾:this指向
- 通过对象调用函数,this指向对象
- 直接调用函数,this指向全局对象
- 如果用new来调用函数,this指向创建的对象
- 如果通过apply,call,bind调用函数,this指向指定的数据
- 如果是DOM事件函数,this指向事件源
使用语法
箭头函数是一个函数表达式,理论上,任何函数表达式的场景都可以使用箭头函数
//函数表达式,例如:
(function(){})()
let fn = function(){}
//函数声明
function fn (){}
完整语法:
(参数1,参数2...)=>{
//函数体
}
如果参数只有一个,可以省略小括号
参数=>{
//函数体
}
如果箭头函数只有一条返回语句,可以省略大括号,和return关键字
参数=>返回值
//如果是返回一个对象,用()包起来
参数=>({...})
细节
- 箭头函数中,不存在this,arguments,new.target,如果使用了,则使用的是函数外层的对应this,arguments,new.target
let obj = {
methed:function(){
let fun = ()=>{
console.log(this);//指向外层函数的this
console.log(argutemts);//外层函数的arguments
}
fun(1);
}
}
obj.method();//this:obj,argutment:[1,...];
- 箭头函数没有原型(占用内存少)
let fn = ()=>{}
console.log(fn.prototype)//undefined
- 箭头函数不能作为构造函数使用
let fn = ()=>{}
new fn();//报错
应用场景
- 临时性使用场景,并不会调用它,比如:
- 事件处理函数
- 异步处理函数
- 其他临时性的函数
- 为了绑定外层this的函数
- 在不影响其他代码的情况下,保持代码的简洁,最常见的,数组方法中的回调函数
粟子:
let arr = [1,2,3];
// let arr1 = arr.map(function(num){
// return num*2;
// })
//用箭头函数代替
let arr1 = arr.map(num=>num*2)