解构赋值:按照一个数据值的结构,快速解析获取到其中的内容
字符串、数字、数组、对象都可以解构赋值(null、undefined不行)但是我们一般只给数组和对象进行解构赋值
让等号左边的数据结构和右边的一样,左边可以创建一些变量,快速获取到右边对应位置的值**解构赋值**
在解构的时候
可以给变量设置默认值
(默认赋值):如果当前变量对应结构的这一项没有值(或者是undefined),变量用默认值;如果当前变量对应结构的这一项null会把null赋值给变量
。...作为剩余运算符时,把除前面以外的项都放在一个数组中;
剩余运算符必须处于结构中的最后面,后面不能有东西
。
数组解构赋值
ler arr=[12,23,34];
//获取每一项
let [a,b,c]=arr;
console.log(a,b,c) //12,23,34
//只获取第一项
let [a]=arr;
console.log(a) //12
//只取某一项
let [,,c]=arr;
console.log(c) //34
//获取第一项和最后一项
let [a, ,c]=arr;
console.log(a,c) //12 34
//把第一项以外的,以一个新数组返回
let [a,..b]=arr;
console.log(a,b) //12 [23,34]
// 剩余运算符必须处于结构中的最后面,后面不能有东西。
let [a,..b,c]=arr;
console.log(a,b,c) //报错 语法错误
//在解构的时候可以给变量设置默认值:如果当前变量对应结构的这一项没有值,变量用默认值
let arr2=[1]
let [a,b=0]=arr2;
console.log(a,b) //1 0
//如果当前变量对应结构的这一项null会把null赋值给变量
let arr2=[1,null]
let [a,b=0]=arr2;
console.log(b) //null
//两个变量互换值
let a=12;
let b=13;
//=>ab互换位置
//传统
let c=a;
a=b;
b=c;
//解构赋值
[a,b]=[b,a]
console.log(a,b) //13 12
对象解构赋值
默认情况下要求左侧变量名和对象中的属性名要一致
设置默认值必须用等号,前面带let或者作为函数的形参时这个变量才能当变量使用
let obj={name:'xxx',age:25,sex:0}
let {name,age}=obj;
console.log(name,age) //'xxx' '25'
//只获取某一个
let {sex}=obj;
console.log(sex) //0
//给解构的属性名起别名,作为变量,起完别名原来的变量名就不能用了
let {sex:sexAA}=obj;
console.log(sex) //报错 sex undefined
console.log(sexAA) //0
//给不存在的属性设置默认值 (必须用=号)
let {id=10}=obj;
console.log(id) //10
//真实使用 函数
let fn=function({name='aaa',age=18} = {}){ //把传递的对象解构了(不传值默认为空对象),解构的时候,可以把传递进来对象中如果没有某个属性,我们赋值默认值
console.log(name,age)
}
fn({
name:'xx',
age:25
})
//步骤解析
let fn=function(option = {}){
let {name='aaa',age=18}=option
}
fn({
nameL:'xx',
age:25
})
例题
let value={name:'xxx',age:25,score:[12,23,34,45] }
//a='xxx'
//b=12
//c=[23,24,45]
let {name:a,score:[b,...c]} =value;
console.log(a,b,c)
“...” 在ES6中的两种含义
剩余运算符:把除前面以外的项都放在一个数组中
拓展运算符( 展开运算符):把数组(对象、类数组)中的每一项展开 xxx,xxx,xxx...
1、放在被赋值一方是剩余运算符。放在赋值一方是扩展运算符
2、当三个点在等号右边,或者放在实参上是展开运算符
3、当三个点(...)在等号左边,或者放在形参上是剩余运算符
剩余运算符
当三个点(...)在等号左边,或者放在形参上
let arr=[12,23,34]
let [...arg] = arr; //跟arr.slice(0)一个效果
console.log(arg) //[12,23,34]
//arguments利用 剩余运算符
function fn(context,...arg){
//获取传递值中的第一个和剩下的
console.log(context)
console.log(arg) //arg 是数组 ,而arguments是类数组
}
var obj={name:'aaa'}
fn(obj,10,20)
function sum(...arg){
//传递几个实参,arg就存储多少个,此时的arg和arguments一样的,区别是arg是一个数组,arguments是类数组
}
展开运算符
当三个点在等号右边,或者放在实参上
展开后必须有容器
把数组中的每一项分别传递给一个函数,此时我们使用展开运算符把数组展开即可
把原有对象展开(克隆),放到新对象中
数组的克隆用slice,或者let newArr=[...arr,100]
let arr= [12,23,34];
//Math.max(...arr)
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
//克隆对象
let obj= {name:'xxx',age:20}
let newObj={...obj,sex:0} //{name:'xxx',age:20,sex:0}
//克隆数组
let arr=[10,20]
let newArr=[...arr,100] //[10,20,100]
let newArr2=[...arr,100,...arr] //[10,20,100,10,20]
let max =Math.max(1,2,3);
//想要处理 Math.max([1,2,3]) 也可用
//es5写法
Math.max.apply(null,[1,2,3]) //3
//es6写法
var arr=[1,2,3];
Math.max(...arr) //Math.max(...arr) =>Math.max(1,2,3) 3
实现任意数求平均数(去掉数字中的最大最小,然后求平均数,保留小数点后两位)
let fn =function(){
//=>arguments:类数组(不能直接调用Array的方法)
//1、先给arguments排序(不能直接用sort)去掉首位
//2、把剩下的求和,除以总长度
let arr=[];
for(let i=0;i<arguments.length;i++){
arr.push(arguments[i])
}
arr.sort(function(a,b){
return a-b;
})
arr.pop();
arr.shift();
//return (eval(arr.toString().replace(/,/g,'+'))/arr.length).toFixed(2); 也行
return (eval(arr.join('+'))/arr.length).toFixed(2);
}
fn(10,9.8,9.5,8.7,8.8,8,9.2)
内置slice利用call能把类数组arguments转化为数组arr的原理:把内置slice的this指向arguments
前提:类数组和数组类似,都有length和索引(字符串也符合这个前提)
重写数组的slice方法实现:arr.mySlice() 相当于把arr克隆为一份新数组
凡是有length和索引的利用[].slice().call(xxx) 都能转化为数组 ;比如把字符串转化为数组
把字符串转化为数组的方法变为了两种
:字符串的split;[].slice().call(str)
Array.prototype.mySlice=function(){
//this:arr
var newArr=[]
for(let i=0;i<this.length;i++){
newArr.push(this[i])
}
return newArr;
/**
let arr=[];
for(let i=0;i<arguments.length;i++){
arr.push(arguments[i])
}
*/
//通过代码对比发现只要把this指向arguments就可以实现 类数组转化为数组
//call、apply都可以
}
let arr=[12,23,34]
arr.mySlice(); //[12, 23, 34]
最终代码:
let fn =function(){
//=>把arguments类数组转换为数组(把数组克隆一份一抹一样的,最后存储在新的数组中)
//调用内置的slice方法的方式:Array.prototype.slice() 或者 [].slice()
let arr=[].slice().call(arguments) //把类数组arguments转化为数组arr
//原理:slice()在mn两个参数都不传的时候是克隆,
//[].slice() slice中的this是[]
//利用call方法把slice中的this转化为了arguments
//相当于克隆了arguments
arr.sort(function(a,b){
return a-b;
})
arr.pop();
arr.shift();
//return (eval(arr.toString().replace(/,/g,'+'))/arr.length).toFixed(2); 也行
return (eval(arr.join('+'))/arr.length).toFixed(2);
}
fn(10,9.8,9.5,8.7,8.8,8,9.2)
[].slice().call('liyapei')
//=>['l','i','y','a','p','e','i']
借用sort给arguments排序
[].sort.call(arguments,function(a,b){
return a-b;
})
数组的方法用call都能被arguments借用
利用ES6把类数组转化为数组let arr=[...arguments]或者let arr=Array.from(arguments)或者(...arr)直接解构
let fn =function(){
let arr=[...arguments] //把类数组转化为数组
//或者,let arr=Array.from(arguments)
arr.sort(function(a,b){
return a-b;
})
arr.pop();
arr.shift();
//return (eval(arr.toString().replace(/,/g,'+'))/arr.length).toFixed(2); 也行
return (eval(arr.join('+'))/arr.length).toFixed(2);
}
fn(10,9.8,9.5,8.7,8.8,8,9.2)
let fn =function(...arr){
arr.sort(function(a,b){
return a-b;
})
arr.pop();
arr.shift();
//return (eval(arr.toString().replace(/,/g,'+'))/arr.length).toFixed(2); 也行
return (eval(arr.join('+'))/arr.length).toFixed(2);
}
fn(10,9.8,9.5,8.7,8.8,8,9.2)