js对象以及对象深复制

对象:

对象是一种以键值对描述的数据格式

=====》 键值对 key:value

分类描述需要用到键值对的方式

所有东西都是对象

字符,数值,布尔值不是用构造函数创建的会放在栈中,如果使用构造函数创建的字符,数值,布尔值都会被放在堆中。但是归根结底他们的根本部分都是对象(object)

//类 父类 子类 超类 对象

类 :就是类别,是对一些具有相同属性和方法的集合做出的抽象概率,类自身也可以是一个对象(类本身可是虚拟抽象概率,也可以是实体存在的对象)

class Box extends Array{
    a=1;
    static b = 2;
    constructor(){
        super();//执行超类的构造函数
    }
    static plays(){
    
    }
    play(){
    
    }
    join(){
        //如果该方法是超类的一个方法时
        super.join();//当需要执行超类的该方法内容时,可以这么写
    }
}

上面是一个抽象类别,描述了一个群体,这个群体中每个对象都有一个a的属性,默认值为1,有一个play方法,只需要通过new这个类就可以创造该类对象

let b = new Box();

let b1 = new Box();

Box相对b,b1这样的对象来说是一个抽象描述

Box变成了对象,其实这里的属性和方法就是对于该种类的属性描述和方法内容,他不是针对实例化的对象产生,而是针对该类别统一描述

Box.b = 10;

Box.plays();

子类 当需要完成一个新的类别时,这个类别是针对某个类别的拓展产生的,这个新的类别就是基于原来类别的新类,也就是我们所说的子类。而原来的而类别相当于拓展出来的新类别来说就是父类

当这种不断拓展产生新的类别时,形成的关系链我们称为原型链

我们将最开始,也就是最底层的父类称为基类,万物的基类就是Object
/子类的父类称为超类,super

对象就是通过实例化类别形成的内容

创建对象 和删除对象

//字面量实例化

var obj = {a:1,b:2};

//构造函数实例化

var obj1 = new Object({a:1,b:2});

//引用地址完全不同

console.log(obj===obj1); //false

//如果需要比对对象的属性和值是否完全相同,可以转换为字符串,然后比对

console.log(JSON.stringify(obj)===JSON.stringify(obj1)); //true

console.log([]===[]);//fasle

console.log([]===true);//false

console.log(![]===false);//true

//以obj对象为原型创建初obj2

//脱离了类别直接以对象继承

var obj2 = object.create(obj);
class Object1{
    a:1;
    b:2;
    constructor(){

    };
}
class Object2 extend Object1{

}
var obj2 = new Object2();
console.log(obj2);
//__proto__原型链
obj.a = 10;//如果原型链对应的对象发生修改,该对象的原型链也会发生改变
obj2.c = 10;
var obj3 = Object.create(obj2);
//当获取对象属性时,如果欸有该对象属性,则查找离其最近的原型链上的该属性,如果有则返回该值
console.log(obj3);

//设置对象属性时,只能设置该对象的对象属性,不能修改对象的原型属性,

//设置一个对象属性时,先查看是否有该对象属性,如果没有则创建一个属性,赋值,如果有了该对象,则修改该对象

//ES5允许直接操作原型链的属性值,但是我们限制只能获取其值,不要修改值

obj3.proto.proto.b=0;//不建议使用原型链修改值

console.log(obj3);

//删除属性和方法

delete obj2.b;//删除对象的对象属性

delete obj2.__proto__.b;//删除原型链属性

obj = null;

obj2.__proto__=obj2.__proto__.__proto__;

console.log(obj2);





Object.assign();

//Object.assign(目标对象,源对象1,源对象2,....);//这个方法返回目标对象



var obj1 = {};

Object.assign(obj1,obj);

console.log(obj1);

var obj1 = Object.assign({},obj);

var obj1 = {c:3};

Object.assign(obj1,obj)

console.log(obj1);

var obj2= {....obj};//目标对象的内容会被覆盖

//如果多源对象赋值,有相同的属性,后面的源对象属性值会覆盖前面的源对象的属性值

var obj2 = Object.assign({},obj,obj1);

console.log(ob2);

Object.assign是浅复制,仅去除了对象的第一层的引用关系,而第二层过着更深的引用关系仍然存在

1.转存失败
2.重新上传
3.取消

//只能赋值对象的可以枚举属性

对象属性定义

var obj = {};

obj.a = 10;

obj["b"]=20;

//对象属性的描述对象(描述属性)

Object.defineProperty(obj,"a",{
    //描述a的属性
    value:10,
    configurable:true,//是否可以删除,以及是否可以修改的描述对象
    enumerable:true,//是否可以枚举
    writable:true,//是否可以修改
});
Object.defineProperty(obj,"a",{
    //描述a的属性
    configurable:true,//是否可以删除,以及是否可以修改的描述对象
    enumerable:true,//是否可以枚举
    //
    set:function(value){
        this._a=value;
    }
    //
    get:function(){
        return this._a;
    }
});
//定义多个属性
var obj = {};
Object.defineProperties(obj,{
    a:{
        value : 1,
    },
    b:{
        writable:true,
        enumerable:true,
        value:2
    },
    c:{
        congigurable:true,
        writable:true,
        value:3
    },
    d:{
        enumerable:true;
        set:functio(value){
            this._d=value
        }
        get:function(){
            return this._d;
        }
    }

});

//获取对象属性名的数组

var arr = Object.getOwnPropertyName(obj);
console.log(arr);

//获取对象属性的描述对象

var desc = Object.getOwnPropertyName(obj,"a");

对象深复制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="div1"></div>
    <div class="div1"></div>
    <div class="div1"></div>
    <script>
        var obj1={};
        Object.defineProperties(obj1,{
            a:{
                value:1
            },
            b:{
                writable:true,
                enumerable:true,
                value:2
            },
            c:{
                configurable:true,
                writable:true,
                value:3
            },
            d:{
                enumerable:true,
                set:function(value){
                    this._d=value;
                },
                get:function(){
                    if(!this._d) this._d=0;
                    return this._d;
                }
            }
        });
        var obj={
            a:1,
            b:[1,2,3],
            c:{
                a:"a",
                b:true,
                c:{
                    a:new Date(),
                    b:/^[a-z](!=[0-9])$/i,
                    c:{
                        a:new XMLHttpRequest(),
                        b:[
                            [1,2,3,4,5],
                            [2,3,4,5,6],
                            [3,4,5,6,7]
                        ],
                        c:{
                            a:[
                                {a:1,b:2},
                                {a:2,b:3},
                                {a:3,b:4}
                            ],
                            b:function(){
                                console.log("aaa");
                            },
                            c:obj1,
                            d:document.querySelector(".div1")
                        }
                    }
                }
            }
        }
        var obj2=cloneObject({},obj);
        // obj.c.c.c.b[0][0]=0;
        // Object.defineProperty(obj.c.c.c.c.c,"c",{
        //     enumerable:true,
        //     configurable:true,
        //     value:3,
        //     writable:true
        // })
        console.log(obj,obj2);
        // console.log(Object.getOwnPropertyNames(document.querySelector("div")));
        function cloneObject(target,source){
            var names=Object.getOwnPropertyNames(source);
            for(var i=0;i<names.length;i++){
                var desc=Object.getOwnPropertyDescriptor(source,names[i]);
                if(typeof desc.value==="object" && desc.value!==null){
                    var objs;
                    if(desc.value.constructor===Date){
                        objs=new desc.value.constructor(desc.value);
                    }else if(desc.value.constructor===RegExp){
                        objs=new desc.value.constructor(desc.value.source,desc.value.flags);
                    }else if(desc.value.__proto__.__proto__ && desc.value.__proto__.__proto__.constructor===HTMLElement){
                        objs=document.createElement(desc.value.nodeName);
                    }else{
                        objs=new desc.value.constructor();
                    }
                    Object.defineProperty(target,names[i],{
                        configurable:desc.configurable,
                        writable:desc.writable,
                       enumerable:desc.enumerable,
                        value:objs
                    });
                    cloneObject(objs,desc.value);
                }else{
                    Object.defineProperty(target,names[i],desc);
                }
            }
            return target;
        }
    </script>
</body>
</html>

setter和getter访问器属性

//ES6以后才能用set和get

//当创建对象时,可以直接使用set和get访问器属性

var obj = {
        _num = 1;
        set num(){
            this._num = value;
        },
        get num(){
            return this._num;
        }
    }
console.log(obj);

//在已有得对象中添加set和get访问器属性

var obj = {};

//不能和writable,value连用,置样使用setter和getter不能使用writable,value

Object.defineProterty(obj,"num",{
    set:function(value){
        this._num = value;
    },
    get:function(){
        if(!this._num) this._num=1;
        return this._num;
    }
})

//ES6类中设置setter和getter访问器

class  Box{
    constructor(){
    }
    set num(value){
        this._num = value;
    }
    get num(){
         if(!this._num) this._num=1;
        return this._num;
    }
    static set nums(value){
        Box._num = value;
    }
    static get nums(){
        if(!Box.num) Box.nums = 0;
        return Box.nums;
    }
}
let b = new Box();
console.log(b,Box);
console.dir(Box);

set和get到底是干啥用的?

var div = document.createElement("div");
div.style.backgroundColor = "red";
document.body.appendChild(div);
Object.defineProterty(div,"w",{
    enumerable:true;
    //set函数得参数有且只有一个,这个参数就是设置属性等于值时,这个设置得值
    set:function(value){
        console.log(value);
        if(typeof value === "number") value+="px";
        this.style.width = value;
    }
    get:function(){
    }
})
Object.defineProterty(div,{
    w:{
          enumerable:true;
            //set函数得参数有且只有一个,这个参数就是设置属性等于值时,这个设置得值
           set:function(value){
            console.log(value);
            if(typeof value === "number") value+="px";
            this.style.width = value;
            }
             get:function(){
                if(!this._w) this._w = 0;
                return this._w;
            }
       }
    h:{
          enumerable:true;
            //set函数得参数有且只有一个,这个参数就是设置属性等于值时,这个设置得值
           set:function(value){
            console.log(value);
            if(typeof value === "number") value+="px";
            this.style.height = value;
            }
             get:function(){
                if(!this._h) this._h = 0;
                return this._h;
            }
       }
})
//所有属性后面有等号,就意味设置该属性,也就会调用set方法
    div.w = 1;
    div.h = 1;
    setInterval(function(){
    div.w++;
    div.h++;
},16)

//所有属性后面没有等号,就意味调用该属性,也就会调用get方法

//一旦使用set get 这种访问属性,该属性不具备属性的存储功能

console.log(div.w);

setter getter 访问器属性
//如果对象中只有一个set,没有get,就说明该属性是只写属性
//如果对象中只有一个get,没有set,就说明该属性是只读属性

var obj = {
        _a = 10;
        get a(){
            return this._a;
        }
    }
class Box{
    a= 1;
    static a = 1;
        consturctor(){

    }
    //可以利用get方法来设置只读属性
    static get  

}

数据结构

数组:所谓数组,是无序的元素序列。若将有限个类型相同的变量名的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称数组元素,有时也称为下标变量。用于区分数组的各个元素的数字编号为下标。数组是在程序设计中,为了处理方便,把具有相同的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。

var arr = [1,2,3,4];

//2 数组元素

//arr[0]—> 0是元素下标

//将无序数据有序的组合

//当数据不需要考虑是针对什么名字,仅仅是以列表的形式出现,以便于循环遍历以及排序,筛选等操作使用

//数组的元素顺序发生变化后,就不能够确定值是针对什么内容,这样也会操作数组的元素无法一一对应使用

//只有使用键值对的形式才会解决一一对应问题

//在数组中元素直接是依靠下标的顺序排列,如果其中删除了一个元素,后面的元素就会向前补位,这样就会造成效率的低下,如果删除数组最前面的元素,它的效率最为低下。

//在有时候不需要重复元素,数组无法判断,形成冗余数组

//数组元素是紧密元素

//let a = new Set();//不重复的值

//集和:键值对(key:value)的形式存在,如果出现集合嵌套问题就叫做多重集合

//object,dictionary

//所有对象的运算都是松散排列

//因为对象是松散集合,因此添加元素,插入元素,删除元素,查找元素,都和其他元素都没有关系

//缺陷:

//元素之间没有关系,因此对象无法针对下一个兄弟关系元素进行操作,也不能统计出整个对象的长度

//在很多语言中使用for…in遍历时,每次遍历的顺序都是随机的(js十个特殊例外,遍历顺序是根据key创建的先后)

let obj = {

a:1,b : 2

}

console.log(on.b);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值