变量解构赋值与默认值
解构赋值
1.什么是解构赋值?
在语法上,就是赋值的作用,解构为(左边一种解构。右边一种解构,左右一一对应进入赋值)
2.解构赋值的分类。
1.左右为数组即为数组解构赋值;2.左右为对象即为对象解构赋值;3.左边是数组,右边是字符串,为字符串解构赋值。
4.布尔值解构赋值为字符串的一种。5.函数参数解构赋值即为数组解构赋值在函数参数的一种应用。6.数值解构赋值为字符串解构赋值的一种。
一、简介
1.(数组解构赋值)
结果:
2.(对象解构赋值)
(输出结果:1 2)
二、默认值、具体使用方法和应用场景(数组解构赋值)
2-1.默认值(数组解构赋值)
(输出1 2 3)
(输出1 2 undefined)
如果解构赋值没有在解构上成功配对(左边3元素,右边2元素,c未找到配对值)默认值为undefined,默认值就是解决声明未赋值的问题。
2-2.使用场景(数组解构赋值)
1.关于变量的交换
(输出:2 1)
无需中间变量做存储,借助解构赋值,解决变量交换
2.取值问题
(输出:1 2)
无需(新变量接受结果,按索引返回0 1位置的值)
3.取值问题
(输出:1 4)(数组的匹配模式)
可以灵活地取出所需要的值。
4.
(输出:1 [2 3 4 5 ])
场景:不知道函数返回数组的长度是多少,只取第一个,其余的不关心。
三、默认值、具体使用方法和应用场景(对象解构赋值)
1.默认值(对象解构赋值)
(输出:42 true)
(输出:3 5 )
2.使用场景(对象解构赋值)
1.前后端服务通信JSON中取值
(输出:abc test)
箭头函数
(1)函数体内的this对象,就是函数声明时所在作用域下的this,而不是使用时所在的对象,箭头函数的this指向永远不变,是静态的。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。
(5)当参数只有一个可以省略小括号,函数语句只有一句必须省略花括号,且函数返回值就是语句返回值。
setTimeOut的this是windows,它是Windows调用的,这时候使用箭头函数可以使this指向当前函数
不适合使用的情况
rest参数
1.这个rest和原来的arguments是有很多相同之处的,不过返回的结果是不同的(用来获取参数的值得)
原来的写法:
----------------------------
function showTeacher(){
console.log(arguments);
}
// 传统的返回的是个对象
showTeacher('中国','france');
----------------------------
返回的结果是个对象:
Arguments(2) ["中国", "france", callee: ƒ, Symbol(Symbol.iterator): ƒ]
2.使用这个rest的形式写法:
---------------------------
function demo(...aggs){
console.log(aggs);
}
demo('ajiao','蔡伦');
--------------------------
返回的结果是个数组:
(2) ["ajiao", "蔡伦"]
-------------------------
3. 如果有多个参数的情况下必须放到最后,后面不包括的参数直接按照数组的方式输出
function demo2(a1,a2,...ag){
console.log(a1);
console.log(a2);
console.log(ag);
}
demo2('one','two','three','four');
返回的结果:
one
two
(2) ["three", "four"]
扩展运算符…
symbol
什么是Symbol
Symbol是由ES6规范引入的一项新特性,它是一种新的基础数据类型,它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例:
let s1 = Symbol()
或者,你也可以在调用Symbol()函数时传入一个可选的字符串参数,相当于给你创建的Symbol实例一个描述信息: let s2 = Symbol('another symbol') 由于Symbol是一种基础数据类型,所以当我们使用typeof去检查它的类型的时候,它会返回一个属于自己的类型symbol,而不是什么string、object之类的: typeof s1 // 'symbol' 另外 每个Symbol实例都是唯一的 ,所以当你比较两个Symbol实例的时候,将总会返回false: const a=Symbol("name"); const b=Symbol("name"); console.log(a===b) //false
应用场景1:使用symbol作为对象属性名
const name=Symbol();
const age=Symbol();
let obj={
[name]:"已经代码"
}
obj[age]=18;
console.log(obj[name]);//已经代码
console.log(obj[age]);//18
并且 当使用了Symbol作为对象的属性key后不能使用枚举方法
const name=Symbol();
const age=Symbol();
const obj={
[name]:"大师",
[age]:16,
sex:"男"
}
console.log(obj)
console.log(Object.keys(obj));//["sex"] 使用symbol定义的属性,不能使用枚举遍历
for(let p in obj){
console.log(p); // sex
}
// 使用Object的API
console.log(Object.getOwnPropertyNames(obj));// ["sex"] 得到符号类型代替的属性名,并且为数组
console.log(Object.getOwnPropertySymbols(obj));// [Symbol(), Symbol()]
const sybs=Object.getOwnPropertySymbols(obj);
console.log(sybs[0]===name) //true 引用会相等
//补充:
1.Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
2.Object.getOwnPropertySymbols()方法返回一个给定对象自身的所有 Symbol 属性的数组。
应用场景2:使用Symbol定义类的私有属性/方法
const Hero=(()=>{
const getRandom=Symbol();
return class Person{
constructor(a,b,c){
this.a=a;
this.b=b;
this.c=c;
}
gongji(){
// const gj=
}
[getRandom](max,min){
return Math.random()*(max-min)+min;
}
}
})()
var per=new Hero(10,20,30,40);
console.log(per); //Person {a: 10, b: 20, c: 30}
// console.log(per[getRandom](10,20)); //报错
// 上面这种方法调用不到,因为现在的[getRandom]在Hero的原型上
const sybs=Object.getOwnPropertySymbols(Hero.prototype)
console.log(sybs); //所以要访问Hero的原型才可以调用输出到
Symbol内置的属性值
Symbol.hasInstance:其它对象使用instanceof运算符的时候会使用该属性名指向的内部方法。
Symbol.isConcatSpreadable:可以直接定义为对象属性或继承而来,它是布尔类型。它可以控制数组或类似数组(array-like)的对象的行为:
1.对于数组对象,默认情况下,用于concat时,会按数组元素展开然后进行连接(数组元素作为新数组的元素)。重置Symbol.isConcatSpreadable可以改变默认行为。
2.对于类似数组的对象,用于concat时,该对象整体作为新数组的元素,重置Symbol.isConcatSpreadable可改变默认行为。
Symbol.species:species 访问器属性允许子类覆盖对象的默认构造函数。
Symbol.match:指定了匹配的是正则表达式而不是字符串。String.prototype.match() 方法会调用此函数。此函数还用于标识对象是否具有正则表达式的行为。
比如, String.prototype.startsWith(),String.prototype.endsWith() 和 String.prototype.includes()
这些方法会检查其第一个参数是否是正则表达式,是正则表达式就抛出一个TypeError。现在,如果 match symbol 设置为
false(或者一个 假值),就表示该对象不打算用作正则表达式对象。
Symbol.replace:这个属性指定了当一个字符串替换所匹配字符串时所调用的方法。
Symbol.search:指定了一个搜索方法,这个方法接受用户输入的正则表达式,返回该正则表达式在字符串中匹配到的下标,这个方法由以下的方法来调用 String.prototype.search()。
Symbol.split:指向 一个正则表达式的索引处分割字符串的方法。
Symbol.iterator:为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。
Symbol.toPrimitive:是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。
Symbol.toStringTag:是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString() 方法会去读取这个标签并把它包含在自己的返回值里。Symbol.unscopables:指用于指定对象值,其对象自身和继承的从关联对象的 with 环境绑定中排除的属性名称。
部分方法及案例
1.Symbol.for()
Symbol.for(key) 会根据给定的键 key,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
示例: Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中,键为 "foo" Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbol
Symbol.for("bar") === Symbol.for("bar"); // true,证明了上面说的 Symbol("bar") === Symbol("bar"); // false,Symbol() 函数每次都会返回新的一个 symbol var sym = Symbol.for("mario"); sym.toString(); // "Symbol(mario)",mario 既是该 symbol 在 symbol 注册表中的键名,又是该 symbol 自身的描述字符串
2.Symbol.keyFor()
Symbol.keyFor(sym) 方法用来获取 symbol 注册表中与某个 symbol 关联的键。
示例:
// 创建一个 symbol 并放入 Symbol 注册表,key 为 "foo"
var globalSym = Symbol.for("foo");
Symbol.keyFor(globalSym); // "foo"
// 创建一个 symbol,但不放入 symbol 注册表中
var localSym = Symbol();
Symbol.keyFor(localSym); // undefined,所以是找不到 key 的
// well-known symbol 们并不在 symbol 注册表中
Symbol.keyFor(Symbol.iterator) // undefined
3.Symbol.toString()
返回当前 symbol 对象的字符串表示。
symbol 原始值不能转换为字符串,所以只能先转换成它的包装对象,再调用 toString() 方法:
Symbol("foo") + "bar";
// TypeError: Can't convert symbol to string
Symbol("foo").toString() + "bar"
// "Symbol(foo)bar",就相当于下面的:
Object(Symbol("foo")).toString() + "bar"
// "Symbol(foo)bar"
示例:
Symbol("desc").toString(); // "Symbol(desc)"
// well-known symbols
Symbol.iterator.toString(); // "Symbol(Symbol.iterator)
// global symbols
Symbol.for("foo").toString() // "Symbol(foo)"
4.Symbol.valueOf()
方法返回当前 symbol 对象所包含的 symbol 原始值。
在 JavaScript 中,虽然大多数类型的对象在某些操作下都会自动的隐式调用自身的 valueOf() 方法或者 toString() 方法来将自己转换成一个原始值,但 symbol 对象不会这么干,symbol 对象无法隐式转换成对应的原始值:
Object(Symbol("foo")) + "bar";
// TypeError: can't convert symbol object to primitive
// 无法隐式的调用 valueOf() 方法
Object(Symbol("foo")).valueOf() + "bar";
// TypeError: can't convert symbol to string
// 手动调用 valueOf() 方法,虽然转换成了原始值,但 symbol 原始值不能转换为字符串
Object(Symbol("foo")).toString() + "bar";
// "Symbol(foo)bar",需要手动调用 toString() 方法才行