1.let-const块级作用域的补充
const names=["abc","cba","nba"];
for(let i=0;i<names.length;i++){ /
m=m|| "aaa";
n=n||"bbb"
console.log(m,n);
}
foo();
foo(100);
foo(100,200)
但在ES6中提供了给函数的参数设置默认值,直接参数后面使用="值"
function foo(m="aaa",n="bbb"){
console.log(m,n);
}
foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200
上面的代码,转化为ES5是这样的:
"use strict";
function foo() {
var m =
arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "aaa";
var n =
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "bbb";
console.log(m, n);
}
foo(); //aaa bbb
foo(100); //100 bbb
foo(100, 200); //100 200
6.1 函数的默认值
// * 可以传基本数据类型
function foo(m="aaa",n="bbb"){
console.log(m,n);
}
foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200
6.7 函数默认值的补充
-
默认值也可以和解构一起使用
function printInfo({name,age}={name:"wjy",age:18}){ console.log(name,age); } printInfo() // * 另外一个写法 function printInfo({name="wjy",age=20}={}){ console.log(name,age); } printInfo()
-
另外参数的默认值我们通常会放到最后(在很多语言中,如果不放到最后其实会报错的)
- 但是Javascript允许不将其放到最后,但是意味着还是会按照顺序来匹配
另外默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内的
// * 有默认值的函数的length属性
console.log(bar.length); //2
function baz(x=20,y,z){
}
console.log(baz.length);//0
7.函数的剩余参数
ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
如果最后一个参数是以...为前缀,那么它会将剩余的参数放到该参数中,并且作为一个数组
那么arguments和剩余参数有什么区别?
- 剩余参数只包含没有对应形参的实参,而arguments包含传递给函数的所有实参
- arguments对象不是一个真正的数组,而剩余参数是一个真正的数组,可以进行数组的所有操作。
- arguments是早期的ECMAscript中为了方便去获取所有的参数提供的一个数据结构,而剩余参数是ES6提供的,并且希望以此替代arguments
剩余参数必须是 函数的参数的最后一个位置,否则会报错。
function foo(m,n,...args){
console.log(m,n);//10 20
console.log(args); //[ 30, 40, 50, 60, 70 ]
}
foo(10,20,30,40,50,60,70)
function bar(...args,m,n){ //*Rest parameter must be last formal parameter
console.log(args);
console.log(m);
console.log(n);
}
bar(1,2,3,4)
8.函数箭头函数的补充
- 箭头函数是没有显式原型的,所以不能作为构造函数
- 箭头函数没有this,箭头函数的this会去上层作用域查找,如果还没有找到,会继续往上查找。直到全局作用域中
- 箭头函数没有arguments
var bar=()=>{
}
console.log(bar.prototype);//undefined
console.log(new bar());//* bar is not a constructor
9.展开语法(Spread syntax)
- 可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开
- 还可以在构造字面量对象时,将对象表达式按key-value的方式展开
const names=["abc","wjy","nba"];
// * 1.函数调用时
function foo(x,y,z){
console.log(x,y,z);
}
foo.apply(null,names);//这种方式也可以,但是阅读性非常差
foo(...names)
let str="wjy";
foo(...str)
// * 2.构造数组时
const newNames=[...names]
//* 3. ES2018 (ES9)构造 字面量对象
let info={
name:"wjy",
age:20,
height:160
}
let newInfo={...info,...names}; //* 数组展开在对象中,key是对应的索引值
console.log(newInfo);
// * 展开运算符其实是一个浅拷贝
9.1 展开运算符的浅拷贝
const info={
name:"wjy",
friend:{
name:"kobe"
}
}
// * 浅拷贝的是拷贝的对象的第一层属性的值,如果拷贝的对象的属性的值引用类型,其实在拷贝的对象中对应的属性的引用的是同一片内存空间
const newInfo={...info}
newInfo.friend.name="hyz"
console.log(info);
10.数值的表示
在ES6中规范了二进制和八进制的写法:
- 二进制:以0b开头
- 八进制:以0O开头
- 十六进制:以0x开头
let num1=100;//默认是10进制
let num2=0b100;//二进制
let num3=0O100;//八进制
let num4=0x100;//十六进制
console.log(num1,num2,num3,num4);//100 4 64 256
// * 大的数值(在ES2021 ES12中),允许使用下划线进行连接
// const num=10000000000;//这种可读性非常差
const num=10_000_000_000;
console.log(num);
11.Symbol的基本使用
Symbol是ES6新增的一个基本的数据类型,翻译为符号。
那么为什么需要Symbol呢?
- 在ES6之前,对象的属性都是字符串形式,那么很容易造成属性名的冲突
- 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是在我们不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖它内部的某个属性
- 比如我们前面实现讲apply、call、bind实现时,我们给其中添加一个fn属性,那么如果它内部原来有一个fn属性了呢?
- 如果在开发中我们使用了混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉。
Symbol就是为了解决上面的问题,用来生成一个独一无二的值
- Symbol的值是通过Symbol函数来生成的,生成后可以作为属性名
- 也就是在ES6中,对象的属性名就可以使用字符串,也可以使用Symbol值
Symbol即使多次创建值,它们也是不同的:Symbol函数每次创建出来的值都是独一无二的
我们也可以在创建Symbol值的时候传入一个描述description:这个是ES2019(ES10)新增的特性
11.1 Symbol作为属性名
// * 3.Symbol作为key
// * 写法1
const obj2={
[s1]:"abc",
[s2]:"wjy"
}
console.log(obj2);
// * 新增:ES2019 ES10新增可以向Symbol传入一个description
obj2[s3]="hyz"
console.log(obj2);
// * 新增
Object.defineProperty(obj2,Symbol("s4"),{
value:"s4",
configurable:true,
enumerable:true,
writable:true
})
// * 获取:只能通过[]获取,不能通过.语法获取
console.log(obj2[s1]);
console.log(obj2.s1);//* undefined 这样是获取不到的,因为通过.获取的时候,会根据后面的名字去对象找对象的属性名为这个的值
// * 4.使用Symbol作为key,在遍历/Object.keys是获取不到Symbol属性值的
// * 需要通过Object.getOwnPropertySymbols来获取所有的Symbol的key
console.log(Object.keys(obj2));//[]
console.log(Object.getOwnPropertyNames(obj2));//[]
console.log(Object.getOwnPropertySymbols(obj2));//[ Symbol(), Symbol(), Symbol(hyz), Symbol(s4) ]
let sKeys=Object.getOwnPropertySymbols(obj2)
for(const item of sKeys ){
console.log(obj2[item]);
}
11.2 相同的key生成相同的Symbol
如果想根据相同的key创建相同的Symbol可以使用Symbol.for(key)
可以通过Symbol.keyFor获取对应的key
// * 5. Symbol.for(key) :如果想要创建一样的Symbol值:通过相同的key创建相同的Symbol
const sa=Symbol.for("aaa");
const sb=Symbol.for("aaa");
console.log(sa==sb);//true
// * 获取key
const key=Symbol.keyFor(sa);
console.log(key);
12.总结
ES6知识点详解.png