字符串模板基本使用
在ES6之前,如果我们想要将字符串和一些动态的变量(标识符)拼接到一起,是非常麻烦和丑陋的(ugly)。 ES6允许我们使用字符串模板来嵌入JS的变量或者表达式来进行拼接: 首先,我们会使用 `` 符号来编写字符串,称之为模板字符串; 其次,在模板字符串中,我们可以通过 ${expression} 来嵌入动态的内容;
const name = "zhangsan";
const age = 18;
const height = 1.88;
console.log(`my name is ${name} ,age is ${age}`);
console.log(`我是成年人吗? ${ age > 18 ? '是' : '否'}`)
function foo() {
return "function is foo";
}
console.log(`mu function ${foo()}`);
标签模板字符串(Tagged Template Literals)。
function foo(...args) {
console.log(args);
}
foo''=>foo()
const name = "why";
const age = 18;
foo`Hello${name}Wor${age}ld`; =>foo() //[hello,wor,ld]
- 如果我们使用标签模板字符串,并且在调用的时候插入其他的变量:
- 模板字符串被拆分了;
- 第一个元素是数组,是被模块字符串拆分的字符串组合;
- 后面的元素是一个个模块字符串传入的内容;
函数的默认参数
- 在ES6之前,我们编写的函数参数是没有默认值的,所以我们在编写函数时,如果有下面的需求:
- 传入了参数,那么使用传入的参数;没有传入参数,那么使用一个默认值;
- 在ES6中,我们允许给函数一个默认值
// ES5 写法
function foo( x , y) {
x = 20 || x;
y = 30 || y;
console.log(x, y);
}
// ES6 写法
function foo( x = 20 , y = 30) {
console.log(x , y)
}
foo(10,20); // 10 20
foo(); // 20 30
foo(0,"") // es5 有bug es6没有bug
//默认值和结构一起用
//写法一
function prantInfo({name,age}={name:'why',age:18}){
console.log(name,age)
}
//写法二
function prantInfo({name='why',age=18}={}){
console.log(name,age)
}
另外参数的默认值我们通常会将其放到最后(在很多语言中,如果不放到最后其实会报错的):
但是JavaScript允许不将其放到最后,但是意味着还是会按照顺序来匹配;
另外默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内了。
函数的剩余参数
-
ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
-
如果最后一个参数是 ... 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;
// 剩余参数只能放到最后面
function foo( m, n, ...args) {
console.log(m, n)
console.log(args)
console.log(arguments)
}
// args 是一个数组 (ES6新增想要替代arguments)
// arguments 是伪数组
// args只包含那些没有对应形参的实参,arguments 对象包含了传给函数的所有实参
foo(20, 30, 40, 50, 60)
那么剩余参数和arguments有什么区别呢?
剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;
parguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;
parguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,
rest参数是ES6中提供 并且希望以此来替代arguments的; 剩余参数必须放到最后一个位置,否则会报错。
箭头函数
箭头函数是没有显式原型的,所以不能作为构造函数,使用new来创建对象
var foo = () => {
console.log("foo");
}
console.log(foo.prototype); //undefined
var f = new foo(); //TypeError: foo is not constructor
箭头函数是没有显式原型的,所以不能作为构造函数,使用new来创建对象
展开运算符(Spread syntax)
可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开; 还可以在构造字面量对象时, 将对象表达式按key-value的方式展开; 展开语法的场景: 在函数调用时使用;在数组构造时使用; 在构建对象字面量时,也可以使用展开运算符,这个是在ES2018(ES9)中添加的新特性;
注意:展开运算符其实是一种浅拷贝;
const names = ["abc", "cba", "nba"]
const name = "why"
const info = {name: "why", age: 18}
// 1.函数调用时
function foo(x, y, z) {
console.log(x, y, z)
}
// foo.apply(null, names)
foo(...names)
foo(...name)
// 2.构造数组时
const newNames = [...names, ...name]
console.log(newNames)
// 3.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: "广州市", ...names }
console.log(obj)
- 展开运算符浅拷贝
const info = {
name: "why",
friend: { name: "kobe" }
}
const obj = { ...info, name: "coderwhy" }
// console.log(obj)
obj.friend.name = "james"
console.log(info.friend.name) // 会被改变成james
数值表示方式
const num1 = 100 // 十进制
// b -> binary
const num2 = 0b100 // 二进制
// o -> octonary
const num3 = 0o100 // 八进制
// x -> hexadecimal
const num4 = 0x100 // 十六进制
console.log(num1, num2, num3, num4)
// 大的数值的连接符(ES2021 ES12)
const num = 10_000_000_000_000_000
console.log(num)
Symbol
- Symbol在通常在对象中表示唯一的属性名
// 在对象中,属性名key是唯一的,相同的会覆盖,但是Symbol就是用来创建一个独一无二的值
// 可以让其不被覆盖
const s1 = Symbol("abc");
const s2 = Symbol("bcd");
console.log(s1.description)//abc
const obj = {};
// 1.写法1:属性名赋值 , 不能使用.的语法
obj[s1] = "abc";
obj[s2] = "bcd";
//obj.s1 = "abc" 错误
// 2.写法2 Object.defineProperty
Object.defineProperty(obj,s1,{
configurable: true,
writable: true,
enumerable: true,
value: "abc"
})
// 3.写法3 字面量
const info = {
[s1]: "abc",
[s2]: "bcd"
};
//使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值
const symbolKyes = Object.getOwnPropertySymbols(info);
// symbol 的key
console.log(symbolKyes)
// 遍历info for of遍历的是value ---- for in 遍历的是key
for (const item of symbolKyes) {
console.log(info[item])
}
- 相同值的Symbol
// 使用for 让描述相同 就可以了
Symbol.for(key)/Symbol.keyFor(symbol)
const s1 = Symbol.for("aaa");
const s2 = Symbol.for("aaa");
console.log(s1 === s2); // true
// keyFor 也可以 key要是 Symbol创建出来的
const s3 = Symbol.keyFor(s1);
const s4 = Symbol.keyFor(s2);
console.log(s3 === s4); //true
const s5 = Symbol("aaa");
const s6 = Symbol("aaa");
console.log(s5 === s6); // false