深拷贝,浅拷贝 set map symbol 模块化

本文介绍了JavaScript中的深拷贝与浅拷贝的概念及其区别,并提供了实现深拷贝的函数示例。接着讲解了Set数据结构的特性,如去重功能,以及如何操作Set的元素。此外,还探讨了Map数据结构,展示了添加、删除和遍历Map元素的方法。最后,文章提到了Symbol的独特性质以及在消除魔术字符串中的应用,以及模块化的概念和优势。
摘要由CSDN通过智能技术生成

深拷贝,浅拷贝 set map symbol 模块化

1.深拷贝和浅拷贝

1.1 深拷贝

定义:拷贝一个对象时,如果属性是复杂数据类型,则拷贝的只是该数据的内存地址。

字面定义:就是将一个对象完全拷贝,并开辟一个新的地址,将拷贝内容放到这个新的地址中,而这个拷贝的对象里面的内容变化不影响原来的对象。
(从字面上的意思理解,是指很深的拷贝,到底有多深呢?深到不仅拷贝值,而且还独立开辟了一个空间。我的理解是:拷贝的过程中,独立地开辟了一个空间,这个对象指向这个地址,与原来的对象互不干扰)

注意:要想达到深复制就需要用递归

1.2 浅拷贝

定义:拷贝一个对象时,如果属性是复杂数据类型,则创建一个新的对象,指向新的对象的内存地址。

字面定义:例如:像是一个人有两个名字,内容是一样的,但名字不一样,当其中的一个名字内容发生变化的时候,其另一个也会发生变化。
(从字面上的意思理解,是指比较浅的拷贝,它与原来的变量仍然指向同一个地址,两者之间相互影响,即其中一个改变会影响另一个的改变。浅拷贝也被称为引用拷贝,引用的意思就是取了个别名,例如张三是大名,狗蛋是他的引用,即为小名,张三变了,狗蛋自然也变了,因为他们本质上就是指同一个人)

深拷贝与浅拷贝的区别

在于是否真正获取一个对象的复制实体,而不是引用。

1.3 案例

<script>
    var obj = {
      a: 1,
      arr: [1, 2],
      nation: '中国',
      birthplaces: ['北京', '上海', '广州']
    };
    var obj2 = {
      name: '杨'
    };
    obj2 = deepCopy(obj, obj2);
    console.log(obj2);
    console.log(obj2.birthplaces == obj.birthplaces);
    //深复制,要想达到深复制就需要用递归
    // 将o对象中的属性复制给c
    function deepCopy(o, c) {
      // 判断c是不是一个undefined或者null
      var c = c || {};
      //遍历对象
      for (var i in o) {
        //判断该属性是不是对象(复杂数据类型)
        if (typeof o[i] === 'object') {
          //再判断是不是数组。Array.isArray  instanceOf
          if (o[i].constructor === Array) {
            //这是数组
            c[i] = [];
          } else {
            //这是对象
            c[i] = {};
          }
          //递归
          deepCopy(o[i], c[i]);
        } else {
          c[i] = o[i];
        }
      }
      return c;
    }
  </script>

2. set()

描述: 类似于数组。 set的值都是唯一的。 但是不能使用索引来获取元素。

结构:值:值

定义: new Set(); 创建一个空的set。

new Set(arr); 创建一个有值的set。

常用属性和方法:add()、delete()、has()、clear()

遍历的方法:forEach (for of)

注意:可以用于数组去重

准备:

var arr = [1, 2, 2, 3];
var ss = new Set(arr);
console.log(ss); //结果:1,2,3 结果不能有重复的值,可以用于数组去重

2.1 用于数组的去重

原因:set的值都是唯一的,里面没有重复的值

// 1. 数组去重
var arr1 = [...ss]
console.log(arr1);//结果:[1,2,3]

2.2 增加元素add()

ss.add(4);
console.log(ss); //结果:1,2,3,4
//增加多个元素
ss.add(5).add(6); //链式,因为set返回值是自身
console.log(ss);

2.3 删除元素 delete()

ss.delete(6);
console.log(ss); //结果:1,2,3,4,5A

2.4 遍历元素

// 4.遍历元素 使用forEach 和 for of不能使用for循环,因为set没有索引是 值:值
ss.forEach((item, index) => {
    console.log(item); //结果:1,2,3,4,5
    console.log('index的值' + index); //结果:1,2,3,4,5
    console.log(index == item); //true
});
console.log('-----------------');
for (let cc of ss) {
    console.log(cc);

}

2.5 判断有没有一个值 has()

返回的是布尔值,有这个值返回true,否则返回的是false

var res = ss.has(4); //结果:有的话返回true 没有返回false
console.log(res);A

2.6 清空 clear()

ss.clear();
console.log(ss); //里面的size是0

2.7 size

// size 查看ss中size中的值
console.log(ss.size);

3. map()

结构:键:值

与object的区别:

  1. object对象的结构也是键值的形式,只不过object的键只能是字符串

  2. map的键和值可以是任意类型

注意: map可以有重复的值,但是不能有重复的键。

定义: new Map();

方法:set(key,values)、get(key)、delete()、clear

遍历的方法:

  1. forEach

​ 回调函数的第一个参数为 键值对中的值

​ 回调函数的第二个参数为 键值对中的键

  1. for of

  2. 属性:size:键值对的个数

准备

    let map = new Map();
    let obj = {name:"潜伏",act:"孙红雷"}
    let obj2 = {title:"谍战",info:"谍战剧是以间谍及地下秘密活动为主题、包含卧底、特务、情报交换、悬疑、爱情、暴力刑讯等元素的一类影视剧"}
    

3.1 增加元素 set()

map.set("肖申克的救赎","剧情")
map.set("潜伏","恐怖");
map.set(obj,obj2);
map.set("九品芝麻官","喜剧")
map.set("西虹市首富","喜剧")

3.2 获取值 get()

let v = map.get("九品芝麻官")
console.log(v);

3.3 删除 delete()

map.delete("潜伏");
console.log(map);

3.4 清空 clear()

console.log(map);
console.log(map.get(obj));

3.5 方法

map.forEach((v,k)=>{
    console.log("v=>"+v);
    console.log("k=>"+k);
})

for (const item of map) {
    //item 是 一个数组,有两个元素。保存了键值对中的键和值。
    console.log(item[0]);
    console.log(item[1]);
}

4. symbol()

定义: Symbol(); 不带new

作用:

  1. 避免对象的属性名冲突

  2. 消除魔术字符串( 魔术字符串:指程序中与代码耦合性非常高的字符串。)

    let a = Symbol();
    let b = Symbol();
    
    console.log(a == b); //false
    

4.1 例子

// A同学  人物金钱: money
let m = Symbol();
let p = {
    name:"史塔克",
    [m]:2000000000
}
console.log(p);
//B 同学 人物攻击力
let s = Symbol();
p[s]= 100;

4.2 消除魔术字符串

//创建一个角色
function createRole(type){
    if (type == race.evles) {
        console.log("创建了一个精灵");
    } else if (type == race.human) {
        console.log("创建了一个人类");
    } else if (type == race.orcish) {
        console.log("创建了一个兽人");
    } 
}
var race = {
    evles:Symbol(),
    human:Symbol(),
    orcish:Symbol()
}

createRole(race.orcish);

4.3 规则

// 我们创建一个symbol变量时,默认情况下打印出来始终都是symbol。 多个symbol变量之间难以区分,所以可以在创建时,添加一个字符串对其进行描述.  Symbol("描述字符")

let a = Symbol("金额");
let b = Symbol("攻击力");

//如果两个symbol的描述字符相等,并不代表他们两个相等。

let c = Symbol("攻击力");

console.log(a);
console.log(b);

console.log(c == b);

4.4 遍历

// symbol类型的属性是无法被 for in for of 等方法访问的。
// ES6提供了一个专门访问symbol属性的方法。  
// let res = Object.getOwnPropertySymbols(对象) 
// res是一个数组,包含了该对象所有属性名中symbol值。

// ES6新增的方法,可以遍历出对象所有的常规属性名和symbol属性名。
//Reflect.ownKeys(p); 
let age = Symbol("年龄");
let k = Symbol("技能")
let p = {
    name: "隔壁老王",
    [age]: 40,
    [k]: function () {
        console.log("修水管");
    }
}
//第二种方法
let res = Reflect.ownKeys(p);
console.log(res);

5. 模块化

JS最开始是没有模块化的概念的。  Java C++

模块化:将一个大型项目按照功能点进行划分。变成一个一个独立的模块。

优点:
1.模块可以独立开发,提高开发效率
2.模块可以复用。

作用:
1.私有化属性
2.避免变量名的冲突

ES5使用闭包+执行函数实现模块化

var 模块名 = (function(){
    return {
        要导出的变量
    }
})()

模块化还未完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值