# 模板字符串
const myName = 'okarin'
const myAge = 18
const myHeight = 1.73
const message = `my name is ${myName},my age is ${myAge}, my height is ${myHeight}`
console.log(message)
1
2
3
4
5
6
7
2
3
4
5
6
7
同时,模板字符串里面可以使用JS表达式
const info = `age double is ${myAge * 2}`
1
const info = `age double is ${doubleAge()}`
function doubleAge(){
return myAge * 2
}
1
2
3
4
5
2
3
4
5
# 标签模板字符串
function foo(m,n){
console.log(m,n)
}
const name = "okarin"
foo`he${name}llo`
//[ 'he', 'llo' ] okarin
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 第一个参数是模板字符串的整个字符串,只是被切成了块,放在了一个数组中。
- 第二个参数是模板字符串中的${ },以此类推。
# 函数的默认参数
function foo(m = 'aaa',n = 'bbb'){
console.log(m,n)
}
foo()
1
2
3
4
5
2
3
4
5
ES6可以给函数参数提供默认值
# 对象参数默认值以及解构
function printInfo({name,age} = {name:"okarin",age:18})
{
console.log(info.name,info.age)
}
printInfo({name:"retr0",age:19})
1
2
3
4
5
6
2
3
4
5
6
function printInfo({name = "oakrin",age = 18} = {})
{
console.log(info.name,info.age)
}
printInfo({name:"retr0",age:19})
1
2
3
4
5
6
2
3
4
5
6
# 默认值的补充
function bar (x , y , z = 30){
console.log(x,y,z)
}
1
2
3
2
3
另外参数的默认值我们通常会将其放到最后(在很多语言中,如果不放到最后其实会报错的):但是JavaScript允许不将其放到最后,但是意味着还是会按照顺序来匹配; 另外默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内了。
# 函数的剩余参数
ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
如果最后一个参数是
...
为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;
function foo(m,n,...args){
console.log(m,n)// 1 2
console.log(args)//[3,4,5]
console.log(arguments)//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
}
foo(1,2,3,4,5)
1
2
3
4
5
6
7
2
3
4
5
6
7
剩余参数和 arguments 的区别:
- 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;
- arguments 对象不是一个真正的数组,而 rest 参数是一个真正的数组,可以进行数组的所有操作;
- arguments是早期的 ECMAScript 中为了方便去获取所有的参数提供的一个数据结构,而 rest 参数是 ES6 中提供并且希望以此来替代 arguments 的;
剩余参数必须放到最后!
# ES6箭头函数的补充
var foo = () => {
console.log("foo")
}
console.log(fo.prototype) //undefind
var f = new foo()//TypeError: foo is not a constructor
1
2
3
4
5
6
7
2
3
4
5
6
7
- 箭头函数是没有显式原型的,所以不能作为构造函数,使用new来创建对象;
# 展开语法(Spread syntax)
可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开;
还可以在构造字面量对象时,将对象表达式按key—value的方式展开;
展开语法的场景:
- 在函数调用时使用;
- 在数组构造时使用;
- 在构建对象字面量使用(ES9新增)
const names = ["abc", "cba", "nba"]
const name = "abc"
const info = {
name: "okarin",
age: "18",
}
function foo(x, y, z) {
console.log(x, y, z)
}
foo.apply(null, names)//abc cba nba
foo(...names)//abc cba nba
foo(...name)//a b c
const newNames = [...names, ...name]
console.log(newNames)//[ 'abc', 'cba', 'nba', 'a', 'b', 'c' ]
const obj = { ...info, city: "chengdu" }
console.log(obj)//{ name: 'okarin', age: '18', city: 'chengdu' }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
注意:展开运算符其实进行的是一个浅拷贝
# ES6表示数值的方式
# 进制
可以使用进制表示
const num1 = 100 //十进制
const num2 = 0b100 //二进制
const num3 = 0o100 //八进制
const num4 = 0x100 //十六进制
1
2
3
4
5
2
3
4
5
# 大的数值(ES12新增)
大的数值的连接符
const num = 10_000_000_000
1
# Symbol的基本使用
Symbol是ES6中新增的一个基本数据类型,翻译为符号。
那么为什么需要Symbol呢?
- 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突;
- 比如原来有一个对象,希望在其中添加一个新的属性和值,但是在不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖掉它内部的某个属性;
- 比如在apply、call、bind实现时,给其中添加一个fn属性,那么如果它内部原来已经有了fn属性了呢?
- 比如开发中使用混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉;
ES6之前,对象的属性名(key)是字符串的形式。
var obj = {
name:"okarin",
friend:{name:"mayuri"},
"age":18
}
1
2
3
4
5
2
3
4
5
而Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
- Symbol值是通过Symbol函数来生成的,生成后可以作为属性名;
- 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值;
const s1 = Symbol()
const s2 = Symbol()
console.log(s1,s2,s1 === s2)//Symbol() Symbol() false
1
2
3
4
2
3
4
# Symbol的描述(description)(ES10)
const s3 = Symbol("aaa")
console.log(s3.description)//aaa
1
2
2
# Symbol的值作为key
- 在定义对象字面量时使用
const s1 = Symbol()
const s2 = Symbol()
const obj = {
[s1]:"abc",
[s2]:"cba"
}
console.log(obj)
//{ [Symbol()]: 'abc', [Symbol()]: 'cba' }
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 新增属性
obj[s3] = "nba"
1
- 通过Object.defineProperty
const s4 = Symbol()
Object.defineProperty(obj,s4,{
enumerable:true,
configurable:true,
writable:true,
value:"bbc"
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意:不能通过obj.属性名
的方式来获取
console.log(obj,obj[s1],obj[s2],obj[s3],obj[s4])
//{
// [Symbol()]: 'abc',
// [Symbol()]: 'cba',
// [Symbol(aaa)]: 'nba',
// [Symbol()]: 'bbc'
//} abc cba nba bbc
console.log(obj.s1,obj.s2,obj.s3,obj.s4)
//undefined
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 获取Symbol的值
注意:使用 Symbol 作为 key 的属性名,在遍历 Object.keys
等中是获取不到这些 Symbol 值的。
- 使用
Object.getOwnPropertySymbols()
获取 Symbol 的 key。
console.log(Object.keys(obj))//[]
console.log(Object.getOwnPropertyNames(obj))//[]
console.log(Object.getOwnPropertySymbols(obj))//[ Symbol(), Symbol(), Symbol(aaa), Symbol() ]
1
2
3
2
3
# 遍历使用Symbol的对象
const sKeys = Object.getOwnPropertySymbols(obj)
for(const s of sKeys){
console.log(obj[s])
}
1
2
3
4
2
3
4
# Symbol.for(key)
- 当需要创建两个一样的Symbol时,使用
Symbol.for()
来创建。 - 当需要获取一个 Symbol 值的 key 时,使用
Symbol.keyFor()
来获取
const aa = Symbol.for("aaa")
const bb = Symbol.for("aaa")
console.log(aa === bb)//true
const key = Symbol.keyFor(aa)
console.log(key)//aaa
1
2
3
4
5
6
7
2
3
4
5
6
7