JavaScript对象

对象

定义对象

<script>
    var obj={a:1}
   	
    key:value
     : 值
    
    键只能是字符串或symbol
    
    如果不加双引号,可以用纯数字或者纯字母,或者首字符是字母后面包含数字或者其他字符,但是不能使用非法字符
    
    如果使用双引号,key可以使用任意字符定义
    
    若果key使用[]定义,可以在[]中使用变量,把变量的值作为属性名
</script>

实例化

<script>
    //实例化对象是在面向对象编程中创建一个对象的过程。
	//使用已经定义的类来创建该类的具体实例,
    //以便在程序中使用这些实例来表示和操作数据或实现特定行为。
    //实例化不仅是在计算机内存中为新创建的对象分配空间的过程,而且使得对象能够访问类中定义的成员变量和方法。
    var obj=new Object({a:1,b:2})
</script>

对象中分为两个部分,一个是属性,一个是方法

属性对应的是方法对应的是函数

 	var obj={
 		a:1,//对应值的叫属性
 		b:function(){}//对应函数的叫方法
       		}

对象的特征

1.有一个名称对应一个值,这种写法叫做键值对,键key,值value,键是唯一的,如果有相同的就会覆盖值

2.要求必须一个键对应一个值,不能仅有键或仅有值

3.键和值是一一对应关系,所以可以通过键直接拿到值(决定了再对象中查找一个值的速度最快,可以直接通过键获取到值)

4.再对象中的存储是非连续的,这个存储是松散型结构,遍历是无序的,不能做排序

5.因为对象的键是无序的 所以添加和删除都不需要考虑位置,直接插入就可以,对象插入,添加,删除速度最快

6.因为对象的键没有记录数量,因此对象是没有长度

对象的操作

  • 对象的操作就是操作里面的数据,分为:增、删、改、查

  • 操作对象上的数据有两种语法:点语法和数组关联语法

  • 点语法

    • 增: 对象名.键名 = 值

    • 删: delete 对象名.键名

      delete 关键词会同时删除属性的值和属性本身删除完成后,属性在被添加回来之前是无法使用的。

      delete 操作符被设计用于对象属性。它对变量或函数没有影响。

    • 改: 对象名.键名 = 值

    • 查: 对象名.键名

    数组关联语法

// 准备一个空对象
var obj = {}
console.log(obj)
// 1. 增加
obj['name'] = '安安'
obj['age'] = 18
obj['gender'] = '男'
console.log(obj) // { age: 18, name: '安安', gender: '男' }
// 2. 删除
delete obj['gender']
console.log(obj) // { age: 18, name: '安安' }
// 3. 修改
obj['name'] = '小安'
console.log(obj) // { age: 18, name: '小安' }
// 4. 查询
console.log(obj['name']) // '小安'
console.log(obj['age']) // 18
console.log(obj['gender']) // undefined

对象操作的区别

对于名字的操作

  • 如果是符合变量命名规则和规范的键名, 两种语法都可以
  • 纯数字只能使用数组关联语法, 不能使用点语法
  • 带有特殊符号的, 只能使用数组关联语法, 不能使用点语法
// 准备一个对象
var obj = {
    a1: 100,
    $5: 200,
    _346: 400,
    1: true,
    2: 'hello world',
    '#abc': 33,
    'font-size': '50px'
}

// 访问
console.log(obj.a1) 
console.log(obj['a1'])

console.log(obj.$5)
console.log(obj['$5'])

console.log(obj._346)
console.log(obj['_346'])

console.log(obj[1])
console.log(obj.1) // 会报错

console.log(obj.#abc);//会报错
console.log(obj['#abc']);

console.log(obj['font-size'])
console.log(obj.font - size) 
// 不行, 变成了 obj.font 和 size 进行减法运算

和变量相关的时候

  • 点语法, 不管如何, 都不能和变量产生联系。始终都是访问的对象内某一个准确的键名
  • 数组关联语法, 当你的 [] 内书写的是一个变量的时候,会把变量解析出来填充在 [] 内
// 和变量相关的访问
var obj = {
    name: '唐僧',
    age: 100,
    1: true
}
var a = 'name'

// 使用点语法的时候
console.log(obj.name) // 访问 obj 内一个叫做 name 的键
console.log(obj.a) // 访问 obj 内一个叫做 a 的键, 和 a 变量没有任何关系

console.log(obj['a']) // 访问 obj 内一个叫做 a 的键, 和 a 变量没有任何关系

console.log(obj[a]) // a是一个变量

注意点

let a={
        name:"aaa",
        age:222
    }
    let b=a;

    console.log(a[name])//不加引号是指一个变量
    console.log(a["name"])//加引号是指键名

对象的key

对象的key只能是字符串类型和Symbol类型,如果不是这两种,则会隐式转换

<script>
    var a="abc";
        var obj={
            a:1,//a是属性  不用于除数值以外其他以数值起头的字符串或者非法字符串包含(除字符,数值,下划线,$以外的字符)
            "b1-a":2,//b是属性   用于全部任何字符串 可以包含非法字符 但是不能使用symbol作为key
            ["c"]:3,//c是属性  []中可以使用任意字符串,任意类型或变量(将把变量的值做为属性名)
            [a]:4,//这里的a没有使用""就是变量,所以把变量的值做为key "abc",这个属性名就是abc
            e:{
                f:1
            }
        }

        // 两种调用方法
        // 如果对象已经定义好了,使用时
        console.log(obj.a) //表示调用obj的a属性
        console.log(obj.e.f) //调用f属性
        // 点语法

        console.log(obj["b1-a"]) //调用b1-a属性  加双引号就是字符串属性
        console.log(obj[a]) //调用变量a属性  不加双引号就是变量
</script>

注意点

		var obj={
            a:function(){//方法
                console.log("aa")
            }
        };
        obj.a();
        obj["a"]();//这个也会执行函数 两种写法是一致的


        // obj.1=1  //错误的写法
        //如果使用点语法,属性名的定义和获取都和变量名定义一致 
        // obj[1]=1; //正确写法

例子

		var o={a:1};
        var o1={b:2};
        var obj={};

        obj[o]=1;
        console.log(obj)//{[object Object]: 1}
        
        //这里obj[o1]中o1是key但是 不是string也不是symbol
        //所以隐式转换为object object  
        //而{object object} : 1  所以其等于1
        console.log(obj[o1]);//1
        
        
        var obj={
            "":1,
            "2":3,
            a:10
        };
        // console.log(obj)//{2: 3, "": 1, a: 10}
        //会进行隐式转换
        var arr=[2];
        // console.log(arr)===2
        
        //下式相当于console.log(obj["2"])===3
        console.log(obj[arr]);//3
        var arr1=["a"];
        //["a"]===a
        console.log(obj[arr1])//10
        //[]===""
        console.log(obj[[]])//1

引用地址

<script>
var str='{"a":1,"b":"abc"}' //JSON字符串

JSON.stringify()
将对象转换为JSON字符串 JSON字符串的要求,属性名必须使用""引起来
JSON.parse()JSON字符串转换为对象

通过JSON转换为字符后 symbol属性不能转换,方法不能转换,不可枚举的不能转换

将 JavaScript 对象转换为字符串,以便可以将其存储或传输


		var obj={a:1,b:2,c:3};
        //当让obj.a=10 时 浏览器会把值缓存 当打印输出时 显示的是缓存中的值
        //通过方式一 obj.a 直接获取对象中的值 此时不会出错
        console.log(obj.a)
        obj.a=10;
        console.log(obj)

        //方式二 就是使用JSON.stringify()
        //先把对象转换成json字符串
        console.log(JSON.stringify(obj));
        console.log(obj)
        obj.a=10;
        //再通过此把对象转换为字符串  就可以获取当时的值
        console.log(JSON.stringify(obj));
        console.log(obj)
</script>
JSON.parse()
通过JSON字符串转换为对象,产生一个新对象,如果字符串不是JSON 格式,就会报错

		var str='{"a":1,"b":"abc"}' //JSON字符串
        console.log(JSON.parse(str));//{a: 1, b: 'abc'}
        
		var a="a";
        console.log(JSON.parse(a))
        //不是对象的字符串 不能通过JSON.parse()转换为对象

例子

<script>
    var obj={a:1,b:2};
    var o1=obj;
    o1.a=10;
    console.log(obj)//{a:10,b:2}
    //o1 与 obj的引用地址是一样的  o1的值改变了  obj中的也会改变
    
    
    var obj={a:1,b:{c:2}};
    var o=obj.b;
    o.c=10;
    console.log(obj)//{a:1,b:{c:10}}
    
    
    var obj={a:1}
    var o1=obj;
    obj={a:2};//此处给了obj新的地址
    console.log(o1);//o不会发生改变 ,o与obj分别代表了不同的对象
    
    
    function fn(o){
            o.a=10;
        }
        var obj={a:1};
        fn(obj);  //此处把函数中的o换成了obj  也就是 obj.a=10
        console.log(obj)//obj变化
    
     function fn(o){
            o={a:10};//此时o换了新地址
        }
        var obj={a:1};
        fn(obj);  
        console.log(obj)//obj不变化
    	// o={a:10};此时o换了新地址
        // o.a=10;没有换新地址  只是更改了引用地址里的值
</script>

对象中的this

<script>
	//对象中的this 防止变量的引用地址发送变化
    
    	var a=20;
        var obj={
            a:1,//key对应的是值就是属性
            b:this.a,//20
            //这里的this指向当前对象外 上下文环境中this(属性中)
            //原因:因为执行到这时,obj还没有执行完毕,无法赋值给obj,只能给window
            c:function(){// key对应的是一个函数,叫做方法
             //谁调用c,this就指向谁,this就是当前对象(方法中)
                console.log(this.a);//1
                console.log(obj.a);//10
            }
        }
        var o=obj;
        obj={a:10};//开辟了新的空间
        // o.c(); 
        console.log(obj)//{a: 10}
        console.log(o);//{a: 1, b: 20, c: ƒ}
  
    	// 方法中的this指向当前对象(方法是执行时才调用)
        // 属性中的this指向当前对象外 上下文环境中this(属性是一开始就赋值)
    
        	var a=0;
            var o={
                a:1,
                b:function(){
                    var a=2;
                    console.log(this.a)
                    var o1={
                 	b:this.a//this指向当前对象外 上下文环境中this  此时是a:1
                    }
                    arr.forEach(function(item){
      					console.log(this);
                        //回调函数中this自动指向window
                },this)
		// forEach的第二个参数就是将回调函数中this重新指向第二个参数
                    console.log(o1);
                }
            }
            o.b();
    
    // 第二个参数时thisArg,可以改变这些函数中回调函数里的this指向
        // [].forEach();
        // [].map();
        // [].filter();
        // [].find();
        // [].findIndex();
        // [].findLast();
        // [].findLastIndex();
        // [].some();
        // [].every();
</script>

对象的内存泄漏

**原因:**堆里面存储的某些对象在引用关系更新之后,不被任何变量引用,这些内容滞留在内存中,就造成了内存泄漏.

清除方法

1.自动调用 浏览器再内存到达一定峰值的时候就会自动调用清除方法(将没有引用地址的清除掉)

2.手动调用(浏览器一般不让手动调用)

<script>
		//{a:1,b:2}的地址分别赋给了 obj和o 但是下面又给obj和o 换了一个新地址  导致{a:1,b:2}不能被回收 也不能被引用  积攒的越来越多就会变成垃圾
        var obj={a:1,b:2};
        var o=obj; 
        // obj和o都指向的是同一个地址{a:1,b:2}

    	//给obj/o更换新地址
        obj={a:10};
        o={b:10};
        // 所以{a:1,b:2}就泄漏了
</script>

null用于对象的清除

<script>
    //垃圾回收
    var obj={a:1,b:2};
    obj=null;//让obj为null  就把{a:1,b:2}的引用列表清除了 {a:1,b:2}就会被清除
    obj={a:10}//给obj新地址
    
    
    var o1={a:1,b:2};
    var o2=o1;//强引用关系
    //此时若是清除o1 {a:1,b:2}并不会被清除,因为{a:1,b:2}的引用列表中有两个定义o1和o2 虽然o1为null但是o2还存在  只有当o2也为null时{a:1,b:2}才会被清除
    o1=null;
    o2=null;
    o1={a:10}//赋予新地址
    
    
		`var o={a:1,b:2};
        var arr=[];//这里还引用着地址,还需要把数组第0项设置为null
        arr.push(o);
        o=null;//此时{a:1,b:2}也不会被清除`
</script>

typeof null 为什么是obj类型?

conslole.log(typeof null)//object

(null针对对象的引用类型设置的)
因为:在JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”

强引用

引用地址相同,一个对象身上存在着多个引用关系,只清除一个不会对另外一个造成影响

弱引用

将一个引用地址,存储在另一个地址中,清除时造成连锁反应,使得对象被清除

例子: o1存的是地址,o2存的是o1的地址,o1如果o1清除了引用关系o2也就清除了

对象的遍历

//判断是不是对象中的一个属性
		var obj={a:1,b:2,c:3};
        console.log("a" in obj);true//判断a是不是obj的一个(键)属性

遍历

注意:

  • 对象没有办法使用 for 循环来进行遍历

    • 因为 for 循环能提供的是一组有规律的数字
    • 但是对象内存放的是键值对,键名是没有规律的
  • 使用for in 来循环遍历

    • for in 的主要作用就是用来遍历对象数据类型

    • 语法:

for (var 变量名 in 对象名) {
    // 重复执行的代码, 对象内有多少个成员, 就执行多少回
    // 对象名[键名] 就是对象中的每一个成员的值
  }
  
  
  
var obj = {
    name: 'jack',
    age: 18,
    gender: '男',
}
for (var key in obj) {
    //拿到所有的键名
    console.log(key);
    
    //拿到所有的键值
    console.log(obj[key]);
}

补充

for...in循环主要用于遍历对象的属性,它返回属性名(字符串类型),适用于遍历对象的属性,而不适用于遍历数组(返回的是数组的索引值)for...of循环适用于遍历数组、字符串、Map、Set等可迭代对象,它返回的是元素的值,而不是索引。(不能直接遍历对象  是迭代器)

foreach 是 JavaScript 中 Array 的一个方法,它可以遍历数组并对数组中的每个元素执行指定操作。



//for in   for of 遍历对象
	const obj={
            a:1,
            b:2,
            c:3
        }
        for(let i in obj){
            console.log(i)//a b c
        }
        for(let i of obj){
            console.log(i)//报错
            console.log(obj[i])//正确
        }
        
//for in   for of 遍历数组
	const arr=['a','b','c']

        for(let i in arr){
            console.log(i)//0 1 2
            //打印的是索引值
        }
        for(let i of arr){
            console.log(i)//a b c
            //打印的是元素值
        }

for in 遍历 补充

1、for in 无法遍历Symbol类型的key

2、 首先按照key转换为数值,如果纯数值的字符串,按照数字从小到大的顺序排列,在这里,小数点和-都是属于字符不算数值,然后再按照属性的添加顺序遍历

<script>
    	var obj={a:1,b:2,c:3};
        //打印对象中所有的键
        for(var key in obj){
            console.log(key);//a b c
        }

        //打印对象中所有的值
        for(var key in obj){
            console.log(obj[key])//1 2 3
        }
    
    
    
     var obj={
            a:1,
        }
        obj.c=3;
        obj.b=2;
        obj[12]=4;
        obj[4]=5;
        obj[1.2]=6
     for(var key in obj){
            console.log(key)
         //排列顺序为:4 12 a b c 1.2
        }
    
    
    var obj={
            a:1,
            b:{
                c:2,
                d:{
                    e:3,
                    f:{
                        g:4
                    }
                }
            }
        }
        for(var key in obj){
            console.log(key)  //只能得到a b
        }
        //要使用递归才能遍历所有
</script>

浅拷贝

只修改第一层的话互不影响

<script>
    	//一层数据
    	var obj={a:1,b:2,c:3,d:4};
        var o={};//此时obj和o分别对应一个地址 彼此之间没有引用关系
    
        //浅复制     深复制需要用递归
        for(var key in obj){
            o[key]=obj[key] //通过循环 把obj中的值复制o中
        }
        obj.a=10;
        console.log(o.a)//1
    
    
    	//两层数据
   	 	var obj={a:1,b:2,c:3,d:4,e:{f:10}};
        var o={};  
    
    	//浅复制 
        for(var key in obj){
            o[key]=obj[key] 
        }
        obj.a=10;
        obj.e.f=100;
        console.log(o.a)  //只改变了外层的引用地址,所以把obj中a对应的值改成10之后  o中的a并不会发送改变
        console.log(o.e.f)//这里o中的f会发送变化,因为是浅复制 只复制了外面的一层,并没有改变内存的引用地址
</script>

深复制

暂时只能用JSON实现(symbol,不可枚举的不能实现)

复制

Object.assign(目标对象,源对象1,源对象2,…)

将所有源对象中的值 赋值给目标对象,后面的会覆盖前面的,并且返回目标对象

<script>
     	var obj={a:1,b:2,c:3,d:4,e:{f:10}};
    	var o={a:10};
        Object.assign(o,obj);//obj中所有值 赋值给o
        obj.e.f=100;//修改obj中e:{f:10}的值
        console.log(o);//{a: 1, b: 2, c: 3, d: 4, e: {f:100}
        console.log(o.e.f)//100
</script>

删除属性

对象中不能删除不可删除属性 比如:arr.length

<script>
    	var obj={a:1,b:2,c:3};

        //删除属性
        delete obj.a;
        delete obj["a"]; //两种形式一样
        console.log(JSON.stringify(obj));
    	//{"b":2,"c":3}
    
    
    	//null 与 delete的区别
    	var obj={a:1,b:2,c:{d:10,e:20}};
        obj.c=null;  //{a:1,b:2,c:null}
        delete obj.c;  //{a:1,b:2}
</script>

数组如果使用delete删除元素,不会补位,不会造成长度减少,会打破紧密关系

	   var  arr=[1,2,3,4];
        delete arr[0];
        console.log(arr)//[empty, 2, 3, 4]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值