对象:
对象是一种以键值对描述的数据格式
=====》 键值对 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
1
}
console.log(on.b);