【JS】ES6新增的方法,Symbol作为属性名,数组和对象的方法

363 阅读5分钟

前言

很多方法因为在类的原型上,作为公共的方法,内部是基于this进行操作的,这一类的方法都可以通过使用call来修改内部的this,然后执行该方法,这样可以让原本不能去调用这些方法的不同的数据类型的数据也可以去使用这些方法,并且达到我们操作这些数据的目的。比如在Array类的原型上,有很多数组的公共方法,这些方法大部分都是通过操作this进行执行的,当我们用call方法修改里面的this,将this改为类数组并执行该方法,这样也可以将类数组里面的数据进行数组的相关操作,比如可以用slice方法克隆类数组里面的数据并且返回的是一个真正的数组。还有很多数组方法都可以通过修改this对类数组进行操作,这样可以让我们操作类数组的时候更加方便。

关于形参的解构赋值

function fn(obj){
let {name,age} = obj;
console.log(name,age);
}
fn({name:1,age:2})// 1   2
---------------------------
function fn({name,age}=obj){
console.log(name,age);
}
fn({name:1,age:2})// 1   2
//这是等价的
----------------------------
//还可以更简单,可以把obj省略,直接在形参的位置解构赋值
function fn({name,age}){
console.log(name,age);
}
fn({name:1,age:2})// 1   2
----------------------------
//还可以形参赋值默认值,如果不传参,就走默认值
function fn({name = 0,age = 0} = {}){
console.log(name,age);
}
fn();// 0  0
fn({name:1,age:2})// 1   2

isArray方法

isArray方法在Array类的里面,是Array类的一个方法,用来检测是否是数组类型的,如果是就返回true,不是就返回false

console.log(Array.isArray([1,2,3]));
// true

这不是ES6的方法。

Symbol作为属性名

由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。

let obj = {age:1};
let age = Symbol();
obj[age] = 100;
console.log(obj);
// { age:1,
     Symbol():100  
    }    

解析:

Symbol作为属性名可以从两个角度分析:

1.防止你新创建的属性覆盖已有的属性

为了防止你新创建的属性的属性名覆盖已经有了的属性名,导致之前的键值对的值被覆盖。为了防止这种覆盖,你可以创建一个唯一值作为属性名,就肯定不会覆盖之前的属性。

2.防止已有的属性被别的属性覆盖

因为Symbol类型的值是唯一的,用其作为属性名的时候,只要定义Symbol类型的变量不一样,Symbol类型的就肯定不是同一个值。所以不管新创建的属性的属性名是什么类型的,只要不是代表已经有了的Symbol类型的属性名的那个变量,就绝对不可能覆盖已经有了的这个Symbol类型的属性名。

let obj = {};
let symbol1 = Symbol();
let symbol2 = Symbol();
obj[symbol1] = 100;
obj[symbol2] = 200;
console.log(obj);
// {Symbol(): 100, Symbol(): 200}

分析: 如本例中,创建Symbol类型的值的时候都是用的Symbol(),但是变量名不同,那么这就是不同的两个数据。作为属性名的时候就不会覆盖。

ES6新增的数组方法

Array.from

Array.from方法主要用于将两类对象转化为真正的数组,一种是类数组对象,一种是可遍历对象。

function fn(){
console.log(Array.from(arguments));
}
fn(1,2,3);
//  [1, 2, 3]

Array.of

Array.of方法用于将一组值转化为数组

Array.of(1,2,3) //  [1,2,3]

该方法弥补了之前构造数组类的实例时的一个缺陷

let ary1 = new Array(3); //[ , , ] 
//这样构造出来的数组是三个空位而不是数组[3]
Array.of(3);// [3]

遍历数组的新方法keys values entries

keys、value、entries方法返回值都是一个遍历器Iterator

//keys 遍历每一个属性名
let ary =[100,200,300,400];
console.log(ary.keys());//返回值是一个遍历器
for(let index of ary.keys()){
console.log(index);//每一个属性名
}
//values 遍历每一个属性值
let ary =[100,200,300,400];
console.log(ary.values());//返回值是一个遍历器
for(let val of ary.values()){
console.log(val);//每一个属性值
}
//entries 遍历每一个属性名和属性值
let ary =[100,200,300,400];
console.log(ary.entries());//返回值是一个遍历器
for(let val of ary.entries()){
console.log(val);//[0,100][1,200][2,300][3,400]
}
//可以使用call改变this,遍历类数组
function fn(){ 
 for(let val of [].entries.call(arguments)){
     console.log(val); 
 }
}
fn(100,200,300,400);

ES6对象新增的方法

Object.assign

用于对象的合并

const target = {a:1};
const source1 = {b:2};
Object.assign(target,source1);
console.log(target);
// {a:1,b:2}

注意: const定义的是常量,但是变量里面存储的是对象时,存储的其实是对象所在的堆内存的地址,地址不会改变,但是堆内存里面的内容是可以改变的。

遍历对象的新方法

Object类里面有keys、values、entries方法用来遍历对象,用法和数组中的对应的方法类似,可以对比的来看。

let obj = {name:1,age:2};
console.log(Object.keys(obj));//["name","age"]
console.log(Object.values(obj));//[1,2]
console.log(Object.entries(obj));
// [["name",1],["age",2]] 

for(let val of Object.keys(obj)){
    console.log(val); //每一个属性名
}
for(let val of Object.values(obj)){
    console.log(val); //每一个属性值
}
for(let val of Object.entries(obj)){
    console.log(val); //每一个键值对用数组进行输出
}

Set内置类

Set实例实现数组去重

Set 的实例实现数组去重,需要用Array.from 或者解构赋值 转化为数组,不然是一个对象就不是数组了

let ss = new Set([1,2,3,4,4]);
let res = [...ss];
console.log(res);// [1, 2, 3, 4]

Set实例实现字符串去重

类似的,Set实例可以实现字符串重复字符的去重,记得去重完需要转化回来变为字符串。

let str = "ababc";
let ss = new Set(str);
str = [...ss].join("");
console.log(str);
// "abc"

注意:

Set的实例没有属性名只有属性值,在使用keys、values、entries 等方法的时候,默认属性值就是属性名,但是不可以使用属性值作为属性名进行成员访问,更不可以使用索引进行访问。字符串去重以后也需要转数组再转字符串,需要转化回来才行。