JavaScript面向对象 [TOC]
实例方法 Object实例对象,就是定义在Object原型对象上的方法,可以直接被Object实例直接使用
1 2 3 4 Object .prototype .print = function ( ) { console .log (this ); }; Object ().print ();
Object本身是一个函数,通过Object()可以把任何数据类型转换为对象
将原始数据类型包装为相应的包装对象是实例
当参数为空时,或者为undefined null 返回的是空对象
instanceof运算符用来判断一个对象是否是某个构造函数的实例
1 2 3 4 function isObject (value ) { return value === Object (value); } isObject ({});
toLocaleString toLocaleString返回本地字符串形式 Array 和Number Date用自己定义的toLocaleString形式,而与toString返回的值不一样 下面就是Date的一个实例对象例子返回不一样
1 2 3 let date = new Date ();console .log (date.toString ()); console .log (date.toLocaleString ());
构造函数 new Object(value)表示新生成一个对象,并且它的值是value,而Object(value)则是将value转换为一个对象,二者的语义是不同的
静态方法 Object.keys();
Object.getOwnPropertyNames(); 1 Object .getOwnPropertyNames ();
Object.prototype.valueOf(); 1 Object .prototype .valueOf ();
Object.prototype.toString(); 1 Object .prototype .toString ();
对一个对象调用toString()方法时,会返回[object,Object]
1 2 3 Object .prototype .toString .call ({}); Object .prototype .toString .call ([]);
1 2 3 4 5 6 function type (value ) { let s = Object .prototype .toString .call (value); return s.match (/\[object (.*?)\]/ )[1 ].toLowerCase (); } console .log (type (null ));
Object.prototype.hasOwnProperty(property) 1 Object .prototype .hasOwnProperty (property);
Object.getOwnPropertyDescriptor() 1 Object .getOwnPropertyDescriptor ();
1 2 3 4 5 6 let obj = {"name" :"jack" };Object .getOwnPropertyDescriptor (obj,"name" );configurable : true enumerable : true value : "jack" writable : true
1 2 3 4 Object .prototype .print = function ( ){ console .log (this ); } console .log (Object .keys (Object .prototype ));
Object.defineProperty() 1 Object . defineProperty() ;
1 2 3 4 5 6 7 let object = Object .defineProperty ({},"p" ,{ value : "我是属性p属性描述对象的value" , writable : true , enumerable : true , configurable : false });
1 2 object.p = "我的值无法被外界修改" ; console .log (object.p );
1 2 Object .defineProperty (object,"p" ,{value : "我的值可以被改变" });console .log (object.p );
1 console .log (delete object.p );
1 2 3 4 5 6 7 8 9 let newObject = Object .defineProperties ({},{ p1 :{value : "我是属性p1中值" ,enumerable :true }, p2 :{value : "我是属性p2中的值" ,enumerable :true }, p3 :{get ( ){return newObject.p1 + "---" + newObject.p2 }, enumerable :true , configurable :true } }); console .log (newObject.p3 );console .log (newObject.propertyIsEnumerable ("p3" ));
如果原型独对象的某个属性的属性描述对象writable的值为false,那么子对象将无法自定义这个属性
1 2 3 4 5 6 let proto = Object .defineProperty ({},"foo" ,{value : "我是属性foo的值" ,writable :false }); let sub = Object .create (proto); console .log (sub.foo ); sub.foo = "我是子对象foo属性的值" ; console .log (sub.foo );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let a = {};Object .defineProperty (a ,'property' ,{ value : "values" , enumerable : false }); for (let key in a){ if (a.hasOwnProperty (key)) console .log (key); } console .log (Object .keys (a));
存储器 相当与java中private修饰变量时使用get和set方法 1 2 3 4 5 6 7 8 9 10 11 12 13 let o = { value :5 , get p (){ return this .value ; }, set p (value ){ if (value > this .value ){return this .value = value;} else throw new Error ("新的值必须大于5,请重新输入" ); } }; o.p = 10 ; console .log (o.p ); console .log (o.p = 4 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let o = { value :5 , p :{ get ( ) { return this .value ; }, set (value ) { if (value > this .value ){this .value = value;} else throw new Error ("新的值必须大于5,请重新输入" ); } } }; o.p = 10 ; console .log (o.p ); console .log (o.p .set (4 ));
对象的拷贝 1 2 3 4 5 6 7 8 let copy = function (newObj,oldObj ){ for (let property in oldObj){ if (oldObj.hasOwnProperty (property)){ newObj[property] = oldObj[property]; } } return newObj; };
若遇到含有存储器的对象,需要使用Object.defineProperty()方法来拷贝对象
1 2 3 4 5 6 7 let extend = function (to, from ){ for (let property in from ){ if (!from .hasOwnProperty (property)) continue ; Object .defineProperty (to,property,Object .getOwnPropertyDescriptor (from ,property)); } return to; };
1 2 3 4 5 6 7 let to = {};extend (to,{foo :"我为foo属性的值" , get ( ){return "我被修改成了" + this .foo }, set (value){this .foo = value;}}); to.set ("Hello World" ); console .log (to.get ()); console .log (to.foo );
注意get() 与 get foo()是不一样的 前者是对象中的一个普通的方法,而后者则是属性foo的属性描述对象中的存储器
控制对象状态 Object.preventExtensions() 防止对象再添加其他的属性 但可以删除旧的属性 但仍可以改变属性的值
1 2 3 4 5 let demoObj = {foo :"我是属性foo的值" ,id :7 ,country :"China" };Object .preventExtensions (demoObj);delete demoObj.id ;console .log (demoObj.id ); console .log (demoObj);
1 Object .defineProperty (demoObj,"p" ,{value :123 });
Object.isExtensible() 检查是否可以向对象中添加新属性
Object.seal() 该方法无法向对象中添加新属性,也无法删除旧的属性 实质是把属性描述对象的configurable变为false 同样可以改变属性的值
Object.isSealed() 检查对象是否使用了seal方法
1 2 3 javalet sealObject={strength :100 }; Object .seal (sealObject); Object .defineProperty (sealObject,"speed" ,{value :120 ,configurable :true });/ can't define property "speed": Object is not extensible
Object.freeze() 使对象无法添加新的属性,也无法删除旧的属性,而且也无法修改属性的值,使得该对象变成了常量
Object.isFrozen() 检查对象是否使用了freeze方法
上面三种方法的局限性就是可以通过改变原型对象来给对象增加属性
1 2 3 4 5 6 7 let protoObject = Object ();Object .freeze (protoObject);let createObject = Object .getPrototypeOf (protoObject);createObject.p = "value" ; console .log (protoObject.p ); console .log (protoObject); console .log (Object .keys (createObject));
还有一件事就是如果对象的属性仍然是对象的话那么这些方法只能冻结属性指向的对象,而无法冻结对象本身的内容,就像const一样,虽然不能改变变量的内存地址但是仍然可以会改变其内容