一、对象概述
1、定义
对象中包含一系列属性,这些属性是无序的。每个属性都有一个字符串 key 和 对应的 value
var obj = { x :1, y:2};obj.x //1obj.y //2
2、对象的 key
访问对象的属性时,无论是 数字,还是字符串都是指向同一个key属性,使用空对象,或有属性的对象,作为key,都会转化为字符串 toString然后处理。
var obj ={};obj[1] = 1;obj['1'] =2;obj; //Object{1:2}obj[{}] = true;obj[{x:1}] =true;obj;// Object{1:2,[object Object]:true}
3、对象结构
1)属性标签
对象的属性可以动态添加和删除的,对象的每一个属性,都有很多的属性标签、get、set方法。
writable 、enumerable、configurable、value、get/set
2)对象原型.
创建一个函数 foo,每一个函数都有一个 prototype属性,假设给 foo.prototype.z赋值为3,这是new一个foo, 这时 obj的原型【[ proto]】就会指向他的构造器的 prototype属性。这时访问 obj.x 得到 1,obj.z 在obj对象上没有,这时会继续找他的原型 z=3。
function foo(){}foo.prototype.z =3;var obj = new foo();
对象中还有【[class]】表示对象属于哪一个种类
【[extensible]】对象是否允许增加新的属性
二、创建对象、原型链
1、字面量 花括号
var obj1 = {x:1 ,y:2};var obj2 ={ x:1, y:2 o:{ //对象嵌套 z:3, n:4 }};
2、new构造器 /原型链
1)原型链
function foo(){}//函数对象默认带一个 对象属性 prototypefoo.protptype.z =3
2)获取值
使用new构造器构造新的对象,每一个对象后含有一个标签原型【proto】,原型指向构造器的 ptototype属性。当烦那个吻对象的属性时,如果对象本身没有这个属性,对象会继续查找原型,直到null,没有返回undefined,有获取到值。
3)赋值
当给对象赋值时不会查找原型链,有则修改,没有则添加。
当设置 obj.z = undefined ;再次获取 obj.z ;// undefined
想要访问原型上的z 则 delete obj .z ; //删除对象上的属性,不会影响到原型链,然后获取 obj.z //3。
4)new创建对象
var o =new Object(); //创建一个空对象 ,和{}一样var a = new Array();//创建一个空数组,和[] 一样var d = new Date();//创建一个表示当前时间Date对象
3、Object .create 创建对象
Object.create()是一个系统内置函数,接收一个参数,一般为对象,返回一个新创建的对象,并且新创建的对象的原型指向参数。参数{ x : 1} 的原型指向 Object.prototype , obj.x x是从原型链继承的。
如果传入一个null,则对象的原型为 null ,不包含任何方法。
四、属性操作
- 读写对象属性
- 属性异常
- 删除属性
- 检测属性
- 美剧属性
1、普通读写操作
对象 . 或者 对象[] 都可以
//创建一个对象var obj = { x:1, y:2};obj.x; //1obj["y"]; //2 obj["x"] =3obj.y = 4
2、动态处理拼接属性名
var obj = {x1:1, x2:2};var i = 1, n = 2;for( ; i<=n; i++){ console.log(obj['x' + i])}
输出:1,2
3、for in遍历
注意用for in遍历,有可能遍历出原型链上的属性。
var p;for( p in obj){ console.log(obj[p])}
4、读写异常
var obj = {x:1}; //创建一个对象//访问一个不存在的属性yobj.y; //先进行原型链查找,如果找到末端还是找不到,返回undefined//obj.y为undefined 再.z报错var yz =obj.y.z ;//TypeError:Cannot read property 'z' of undefinedobj.y.z = 2; //TypeError:Cannot set property 'z' of undefined
1)、读写前判断
var yz;if(obj.y){ //先判断是否有y属性 yz= obj.y.z}//或者 && 判断 每个都是true 整体返回truevar yz = obj && obj.y && obj.y.z//obj存在则继续向右找,如果为空直接返回 undefined
5、删除属性
1)delete意义 :
当对象上不存在要删除的属性时就会返回true,重复删不会报错
var person = {age:28,title:'fe'};delete person.age ; //true 删除成功delete person['title']; //true 中括号传入key删除成功person.age ; //undefineddelete person.age; //true 重复删除不存在的属性不会报错,返回true
2)不允许删除的属性
delete Object.prototype; //false //getOwnPropertyDescriptor 第一个参数时要查看对象,第二个参数是要检测的属性var descriptor = Object.getOwnPropertyDescriptor(Object,"property"); //获取属性中所有的标签descriptor.configurable ;//false 是否可配置:false ,所以delete Object.prototype返回false
3)var 定义的全局变量 局部变量也不能被删除。
var globalVal = 1; //定义全局变量delete globalVal; //false 不可以删除(function(){ var localVal = 1; return delete localVal; //不可以删除}());//false
4)全局函数,局部函数也不可以delete
function fd(){}delete fd;//false 删除失败(function(){ function fd(){ return delete fd; }}()); //false
5)隐式创建全局变量可以删除
ohNo = 1; //隐式创建全局变量window.obNo; //1delete ohNo;//true 成功删除 但不推荐
6、属性操作
1)查看属性是否存在
var cat = new Object; //构造一个对象cat.legs = 4;cat.name = "Kitty"'legs' in cat ;// true cat中有legs属性'abc' in cat ; //false"toString" in cat; //true, inherited property cat原型是Object.prototype,中toString存在//表示查找对象上的属性cat.hasOwnProperty('legs'); //truecat.hasOwnProperty('toString'); //false,原型链上存在
2)查看属性是否可枚举
cat.propertyIsEnumerable('legs'); //true 可以枚举cat.propertyIsEnumerable('toString'); //false
3)设置属性
Object.defineProperty
Object.defineProperty(cat,'price',{enumerable:false,value:1000});Object.defineProperty 创建对象标签都默认为false//第一个参数:添加属性的对象。2、属性的名字,3、对象,设置标签cat.propertyIsEnumerable('price'); //falsecat.haOwnProperty('price');//true
5)操作属性时判断属相是否存在
if( cat && cat.legs){ //存在 cat.legs*=2; }//或 !=时 null 和undefined是相等的if(cat.legs != undefined){ //还可以写为 !==undefined}
6)属性枚举
var o = { x:1, y:2,z:3}'toString' in o; //trueo.propertyIsEnumerable('toString'); //falsevar key;for(key in o){ //遍历属性,由于toString是不可枚举的所以不显示 console.log(key) ;//x,y,z}
利用 Object.create(o) 创建一个 obj对象 原型指向o。此时原型链o上的属性夜默认可枚举
var obj = Obj.create(o); //原型链上的属性也默认可枚举obj.a = 4; //添加一个属性a 默认可枚举var key;for(key in obj) { console.log(key) ; // a,x,y,z}
只操作本对象上的属性
var obj = Object.create(o);obj.a = 4;var key;for(key in obj){ if(obj.hasOwnProperty(key)){ //过滤掉原型链的属性 console.log(key);//a }}
五、另一种读写方式 get/set方法
1、属性getter/setter方法
定义 get 、set方法访问属性age()
var man = { name:'Bosn', weibo:'@Bosn', get age(){ // get关键字 属性名 函数体 return new Date().getFullYear() - 1995; //返回当前日期年份减去生日,算出当前年龄 }, set age(val){ console.log('Age can\'t be set to' +val ); }}console.log(man.age); //22 获取值时自动调用 get方法man.age = 100; //Age can't be set to 100 赋值时自动调用set方法console.log(man.age); // still 22
2、get/set与原型链
当访问 obj.z,由于对象上没有z属性,会向原型链上查找,给z赋值后,发现obj.z仍然为1。 当obj对象上没有z属性,并且发现在原型链上有对应的get 或 set 方法时,当尝试赋值时会走get/set方法,而不会给对象添加新的属性。
1)原型链上的属性具有get/set方法
用 Object.defineProperty( obj,'z',{}); 来给obj对象添加z属性,这时 obj.z为100 ,删除obj.z ,再次获取 obj.z 获得原型链上 z的get方法 返回1
2)原型链上的writable 为false
定义一个空的对象 o,定义属性x ,注意通过 Object.defineProperty() 定义的对象,各个标签的默认是false ---writable = false, configurable = false。在创建一个以o作为原型的新对象, 修改x的值,不起作用,因为原型链上的writable = false,不可改
给obj对象添加属性,使用Object.defineProperty()
var o {};Object.defineProperty(o,'x',{value :1});//writable = false, configurable = falsevar obj = Object.create(o); //创建一个以o为原型的新对象obj.x ;//1obj.x =200; //修改obj.x; //still 1 can't change it//给obj添加属性xObject.defineProperty( obj ,'x',{writable:true,condigurable:true, value :100});obj.x = 100;obj.x = 500; //修改obj.x = 500; //修改成功
六、属性标签
1、查看属性标签
- getOwnPropertyDescriptor 接收两个参数 1、要判断的对象 2、字符串类型的属性名
- writable:属性是否可修改
- enumerable:属性是否可遍历,在for in中是否可显示
- configurable:属性标签是否可再被修改,是否可以delete
Object.getOwnPropertyDescriptor({pro:true},'pro');//返回一个对象 Object {value:true,writable:true,enumerable:true,configurable:true}Object.getOwnPropertyDescriptor({pro:true},'a'); //不存在a属性 undefined
2、设置属性标签
Object.definedProperty 创建属性,
var person = {} ;//空对象//传入对象,属性名,配置对象{}Object.definedProperty(person,'name',{ configurable:false, writable:false, enumerable:true, value:'lalala'})person.name;// lalalaperson.name = 1; //修改后仍然为1delete person.name; //false
继续添加属性
Object.definedProperty(person,'type',{ configurable:true, writable:true, enumerable:false, //不可枚举,在for in 中不显示type属性 value:'hahaha'})//获取对象上所有的keyObject.keys(person); //['name']
3、添加多个属性标签
Object.defineProperties ( 定义属性的对象,{ 属性名:{设置值},属性名:{...} })
Object.defineProperties(person,{ title:{ value:'chapter1' , enumerable:true}, //默认值为false salary: {value:10000,enumerable:ttue}, luck:{ //随机一个数,一般概率good get : function(){ return Math.random()>0.5 ? 'good','bad'} }, promote :{ //升一级,工资涨10% set: function(level){ this.salary* = 1+level*0.1} }})Object.getOwnPropertyDescriptor(person,'title');//得到一个 Object {value:'chapter1' , enumerable:true, writable:true,configurable:false};person.salary; //1000person.promote = 2; //调用set方法 person.salary ;12000;
只要configurable:true, 就可以用Object.defineProperties修改值 或标签值
七、对象标签、对象序列化
1、对象标签
对象的每一个属性都是有标签的,对象也有
[ [proto] ] 、[ [class ] ]、 [[extensible]]
1)原型标签 _proto_
2)class标签
表示对象时哪个类型的
slice(8,-1); //从第8个字符截取直到最后,去掉最后一个字符,toString 会把值转换为对象
3)extensible标签
对象是否可扩展,preventExtension (obj) ;//设置为禁止扩展,对象不可以在添加对象,但对象属性的标签值不会改变。
Object.seal(obj); //将所有对象的configurable属性设置为 false。
Object.freeze(obj); //冻结,writable,configurable 都为false
2、序列化其他对象的方法
1)序列化
JSON 属性要用 " " 引起来
var obj = { x:1,y:true,z:[1,2,3],nullVal:null};JSON.stringify(obj); // 返回一个字符串 "{"x":1 , "y":true, "z":[1,2,3],"nulVal" :null}"//如果序列化的值为undefined,则这个值不会出现在序列化对象中obj ={ val :undefined, a :NaN , b:Infinity, c:new Date()};JSON.stringify(obj); // "{"a":null , "b":null, "c":"2017-04-20T14:14:43.910Z"}";//值为 notNumber 、Infinity 获得 null 。时间获得UTC时间格式//反解对象obj = JSON.parse('{"x" :1 }'); obj.x; //1
2)序列化自定义
var obj = { x:1, y:2, o:{ o1:1, o2:2, toJSON : function(){ //固定toJSON return this.o1 + this. o2 ; //this 指向o } }};JSON。stringify(obj); //"{ "x":1, "y" :2, "o" :3}"
3)其他对象方法
var obj = {x:1,y:2};obj.toString(); //"[ object object]" 返回 objectobj.toString = function(){ return this.x + this.y}; //定义自己的toString方法"Result" + obj; //"Result3, 理解为字符串拼接,调用 toString +obj; //调用tostring方法,转化为数字,相加 得3//valueOf 尝试把对象变为基本类型时调用obj.valueOf = function () { return this.x + this.y + 100; };//无论是 转化为数字,还是拼接都会尝试把对象转化为基本类型,先去找valueOf,如果valueOf不存在,或返回对象,则toString,如果toString也不存在,或者返回对象则报错+obj; //103 从 valueOf来的"Result" + obj ;// "Result103"