js 对象 详解
发布日期:2022-02-08 04:21:00
浏览次数:3
分类:技术文章
本文共 8033 字,大约阅读时间需要 26 分钟。
一、对象的创建和应用
1、之前学过的创建方法
1、字面量创建法:var obj={ a:1,b:2};console.log(obj);2、构造函数创建法:var obj=new Object();obj.a=1; //增加属性obj.b=2;
2、Object.create()方法创建
1、根据空对象创建:var obj1=Object.create({ });2、根据已有对象创建:var obj1=Object.create(obj);console.log(obj2,obj1);3、获取,会先查找该对象下有没有该属性,如果没有就去原型链中查找:console.log("obj1.b:"+obj1.b);
打印查看结果:根据obj创建的obj1,继承于obj的属性被放在了__protp__原型链属性中。
4、_ _ proto _ _:原型链属性 被放在原型链下的属性,叫原型属性; 直接放在对象下的属性,叫对象属性;如果想要修改原型链属性,只需要修改最顶端的对象的属性即可;比如obj.b = -10;obj1与obj2原型链中的b都会变成-10 。
如果该对象有对象属性,就可以直接获取对象属性;如果没有对象属性就会获取距离该对象最近的原型链属性。设置属性时,只会设置对象属性,不能设置原型链属性。obj1.b = 10;console.log(obj1);console.log("obj1.b="+obj1.b); //obj1.b=10var obj2=Object.create(obj1);console.log(obj2);
原型、原型链其实是一个东西,只是针对的东西不一样。原型针对类,原型链针对对象,但他们的引用完全相等。
原型是指类中用来描述该类实际特征、属性、方法的;
如果直接在类上写属性 、方法,是静态方法;而如果用原型,上面所描述的属性、方法,实例化后,就可以通过实例来调用该方法。
原型链是实例化类以后的对象,会自动拥有类自身的原型。
有篇文章,介绍原型、原型链的,我觉得挺好:
5、禁止使用这种方式进行修改:
obj2.__proto__.__proto__.b=-100; //绝对不允许console.log(obj);console.log(obj1);console.log(obj2);
6、原型链中的属性不能被直接删除:
var obj = { a: 1, b: 5 };var obj1 = Object.create(obj);delete obj1.b; console.log(obj1);7、对象属性可以直接删除;原型链中的属性可以获取到:
var obj = { a: 1, b: 5 };var obj1 = Object.create(obj);var bn = document.querySelector("button");bn.addEventListener("click", clickHandler);function clickHandler(e) { obj1.b++; // if(obj1.b>=10) obj1.b=obj1.__proto__.b; //可以获取原型链里的属性,重新赋值 if (obj1.b >= 10) delete obj1.b; //删除对象属性,下次还是会去原型链中查找最近的 this.textContent = obj1.b;}
结果:按钮从无到有,从5到9,在5~9之间来回变换
8、对象属性的删除var obj={ };var obj1={ b:2};obj.a=obj1; // obj1作为obj.a一个对象属性delete obj.a; //删除对象属性,但没有删除引用关系obj1=null; //这样才彻底删除引用关系但有种情况是没法使用上面的方法删除的:var obj={ a:{ b:2}};// 这个时候用delete直接删掉obj.a的话,obj.a是会变成孤儿对象,造成内存引用泄漏;// 但下面的就可以了:先删除引用关系,再把这个对象属性删掉obj.a=null;delete obj.a;
3、Object.assign()方法创建
Object.assign(目标对象,源对象1,源对象2,… ); 返回目标对象;
Object.create()通过原型创建对象,把另一个对象作为原型放入新对象的原型链中,可以创建对象; Object.assign()是不能创建对象的,必须拥有目标对象才能创建;<1> obj1不存在,也可以被直接创建var obj={ a:1};var obj1=Object.create(obj);<2> obj1必须先创建存在var obj1={ }; obj1=Object.assign(obj1,obj);// 或者使用下面的写法,先创建了一个空对象,然后将obj复制到这个空对象上:var obj1=Object.assign({ },obj); // 这个空对象和obj1引用相同
1、所以Object.assign只能复制对象属性,不能复制对象的原型链属性
2、只能复制可枚举类型 3、引用关系也会一同被复制,只能浅复制 4、多个源对象复制时,如果有相同的属性,则后面的将会覆盖前面的属性var obj={ a:1,b:2};var obj1={ b:3,c:10};var obj2 = Object.assign({ }, obj, obj1);console.log(obj2); //{a: 1, b: 3, c: 10}// 其他用法Object.assign(div.style,{ // 我们之前不是经常这么写样式嘛})
二、对象的属性定义 & 获取
1、之前我们用的对象属性定义方法
obj.a=3;obj["b"]=5;仅仅定义了值,没有定义引用,复杂的就不行了。
2、Object.defineProperty()
- 1、功能:定义属性。 原型链属性是不可以被修改描述对象的。
var obj = { _b:1}; 三个参数: 对象 对象属性 描述对象Object.defineProperty(obj, "a", { // 是否可删除属性并且是否可以重定义该属性的属性描述对象,默认值是false: configurable: false, // 是否可以遍历,是否可枚举(该对象在使用for in遍历时,不可枚举属性是不能被遍历,也不能被Object.assign()复制 ): enumerable: false, // 是否可写,是否能够修改值: writable: false, // 是值,还可以是function方法: value: 10,});后面再来讲解get和set,get和set不能够和writable和value同时定义,所以分开展示了:Object.defineProperty(obj, "b", { configurable: false, enumerable: false, // get和set不能够和writable和value同时定义 get: function () { return this._b; }, set: function (value) { this._b=value; }})
- 2、定义一个obj,里面有函数abc,用for in遍历的话,会遍历函数abc;所以如果想要只遍历属性,就不能用这种方法。
var obj={ a:1, b:2, abc:function(){ console.log("abc") }}for(var prop in obj){ console.log(prop);}
- 3、如果把该属性函数的描述对象里设置成 enumerable:false,就不会遍历:
var obj0 = { a: 1, b: 2}Object.defineProperty(obj0, "abc", { // 其实下面这三句可以不写,不写,默认false // enumerable:false, // configurable:false, // writable:false, value: function () { console.log("abc") }});console.log(obj0);// 只遍历属性了,不会遍历函数abc(不可枚举)for (var prop in obj0) { console.log(prop);}// 然后此时再用Object.assign()就不会复制方法var obj1 = Object.assign({ }, obj0);console.log(obj1);
- 4、定义多个属性 & 将属性返回 & 获取描述对象
Object.defineProperties(obj,{ "c":{ // 描述对象 value:function(){ } }, d:{ // 描述对象 value:10, writable:true }, e:{ value:20, writable:true, configurable:true }, f:{ value:30, enumerable:true }});console.log(obj);(1)不过除了enumerable:true的,以上那些属性都没法遍历;(2)不过可以通过获取obj的所有属性(不包括原型链属性__proto__),把所有的属性名放在一个数组中返回:var arr = Object.getOwnPropertyNames(obj);console.log(arr);(3)获取某个属性的描述对象:var desc = Object.getOwnPropertyDescriptor(obj, "f");console.log(desc);
三、对象浅复制&深复制
浅复制:有相同的引用,比如说,新对象改变了其中一个对象属性后,源对象里该对象属性也改变了。
深复制:源对象的属性如果有对象,该对象属性修改后,不会引起复制后的对象各属性的改变,源对象的任何属性及子属性,与新对象的没有任何引用关系。
目前学的浅复制的方法:
1、for in 看不到不可枚举属性,不遍历空属性for(var prop in obj){ // 浅复制}2、Object.assign();//浅复制3、var obj1={ ...obj};//浅复制,obj作为一个对象属性;如果原obj1就存在,还会改变原obj1的引用地址4、JSON字符串,表面上看是深复制,但其实,复制的不完全;所以既不是深复制,也不是浅复制。var obj1=JSON.parse(JSON.stringify(obj));//不能达到真正的复制console.l(obj1,obj);//可以自己看一下,有很多不同
目前学的深复制的方法:之前讲过很多例子,自己去翻翻以前的笔记。
下面要展示一个特别全活的深复制例子,这个很重要:
四、对象的其他方法集合
Object.freeze()
- 冻结的对象不能增加属性,不能重新设置属性,不能删除,也不能重新设置属性的描述对象。
- 对象自身是可以删除的,只是对象所对应的属性,都是被冻结的。
var obj={ a:1,b:2};Object.freeze(obj);// 对象冻结后,不能增加属性obj.c=30;// 不能重新设置属性obj.a=1000;// 也不能删除属性delete obj.a;console.log(obj);//虽然能够打印出来,但是obj没有任何改变// 不能重新设置属性的描述对象Object.defineProperty(obj,"a",{ configurable:true, writable:true, enumerable:true, value:3000})console.log(obj);//出错了// obj自身是可以删除的obj=null;console.log(obj);//null
- 对象被冻结后,使用Object.assign()与Object.create()
// obj虽被冻结,但可以用于复制,并且复制后的属性是可以删除和修改的var obj1=Object.assign({ },obj);obj1.a=10;console.log(obj1);var o=Object.create(obj);//属性描述特征是被继承过去的// 首先判断对象有没有原型属性a,如果有,还需要看原型属性a是否冻结,如果冻结则不能增加对象属性o.a=10;//不能o.c=10;//能增加,因为o没有被冻结console.log(o);
判断对象是否冻结的两种方法 Object.isExtensible()、Object.isFrozen()
- Object.isExtensible() 判断当前对象是否可扩展:若对象被冻结,结果为false,则为不可扩展;若为true,则可以扩展。
- Object.isFrozen() 判断当前对象是否冻结:若对象被冻结,结果为true;否则,未被冻结。
var obj = { a: 1 };Object.freeze(obj);console.log(Object.isExtensible(obj));// false 不可扩展console.log(Object.isFrozen(obj));// true obj被冻结
所以,判断对象冻结有以上两种判断方法。
Object.is()
- 比较数据和数据的类型,等同于" === " 的用法。
var a=3;var b="3";console.log(Object.is(a, b));//false 类型不等console.log(Object.is([],[]));//false 引用不同var a = 3; //数值类型var b = new Number(3); //对象类型 创造数值型对象console.log(Object.is(a, b)); //false 类型不等var b=Number(3);//强制转换为数值3 数值类型console.log(Object.is(a, b)); //true// 很特殊的例子:(其他都跟 === 用法一样)console.log(Object.is(NaN, NaN));//trueconsole.log(NaN === NaN);//false
hasOwnProperty() 与 in
- hasOwnProperty()判断对象实例是否具有某个对象属性。
- hasOwnProperty()方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身的一个成员。
- 如果该属性或方法是该对象自身定义的而不是原型链中定义的,则返回true;否则返回false。
- in判断的是对象的所有属性,包括对象实例及其原型的属性。
var obj = { a: 1};console.log(obj.hasOwnProperty("a"));//trueconsole.log(obj.hasOwnProperty("b"));//falsevar o=Object.create(obj);console.log(o.hasOwnProperty("a"));//false 原型属性不是当前对象的对象属性console.log("a" in o);//true in判断属性是否是对象属性时,只要是该对象的原型属性和对象属性都可以判断
isPrototypeOf()
- isPrototypeOf() 是用来判断指定对象object1是否存在于另一个对象object2的原型链中,是则返回true,否则返回false。
- 或者这么理解,object2._ _ proto _ _ ==== object1.prototype ? true:false 。
var obj = { a: 1};var o=Object.create(obj);var o1=Object.create(o);o.a=10;o1.a=1000;console.log(o.isPrototypeOf(obj));//false console.log(obj.isPrototypeOf(o));//true obj是o对象的原型console.log(o,o1);console.log(obj.isPrototypeOf(o1));//true obj是o1的原型链中的一个console.log(o.isPrototypeOf(o1));//true o也是o1的原型链中的一个
- 类中,isPrototypeOf 可以判断某个类的父类是否是这个指定类。
- 语法:父类.isPrototypeOf(子类)
class Box { a = 3; constructor() { }}class Ball extends Box { b = 10; constructor() { super(); }}class Rect extends Ball { c = 20; constructor() { super(); }}var rect=new Rect();console.log(rect);// 说明Rect继承于Ball,Ball继承于Box,所以Rect的父类当中有Box、Ballconsole.log(Box.isPrototypeOf(Rect));//true console.log(Ball.isPrototypeOf(Rect));//true
propertyIsEnumerable
- propertyIsEnumerable 判断是否是可枚举属性。
var obj={ a:1,b:2};Object.defineProperty(obj,"b",{ enumerable:true //设置可枚举});Object.defineProperty(obj,"c",{ value:3000});var names=Object.getOwnPropertyNames(obj);console.log(names);for(var i=0;i
转载地址:https://blog.csdn.net/weixin_43297321/article/details/104368934 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月09日 07时17分11秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
中文代码示例之NW.js桌面应用开发初体验
2019-04-26
为《 两周自制脚本语言 》添加中文测试代码
2019-04-26
将《 两周自制脚本语言 》测试中使用的接口中文化
2019-04-26
5分钟入门LingaScript-尝鲜中文版TypeScript
2019-04-26
重拾《 两周自制脚本语言 》- 支持中文标识符
2019-04-26
Java实现文本编辑时基于拼音输入的补全原型
2019-04-26
从立创EDA,Gratipay看中文编程开发环境和推广运营的一个趋势
2019-04-26
中文代码之Django官方入门:建立模型
2019-04-26
Python实现推流直播
2019-04-26
你不得不了解的卷积神经网络发展史
2019-04-26
你不得不了解的机器学习知识
2019-04-26
你不得不了解的深度学习知识(一)
2019-04-26
你不得不了解的深度学习知识(二)
2019-04-26
AI算法之Encoder-Decoder 和 Seq2Seq
2019-04-26
AI算法之Attention机制
2019-04-26
人体口罩佩戴检测实战
2019-04-26
[实战]200类鸟类细粒度图像分类
2019-04-26