1 对象的概述
对象包含一系列的属性及方法,这些属性是无序的,每个属性都有一个字符串key和对应的value
对象的结构包括:属性、方法、标签([[class]] [[proto]] [[extensible]]),属性也具有属性标签(writable,enumerable,configurable,value,get/set方法)
对象的序列化和反序列化及toString(),valueOf方法
2 创建对象的方式
- 字面量的方式
- 使用new关键字
- 使用Object.create(obj)
//字面量的方式
var girl = {name: "cindy", age :22};
//使用new关键字 后面跟构造函数吖
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
}
var luckGirl = new Person("hua",18);
//使用Object.create(obj);
var sGirl = Object.create(girl);
3 原型链
luckGirl.__proto__ == Person.prototype;
Person.prototype.__proto__ == Object.prototype
Object.prototype.__proto__ == null
4 对象的属性操作
- 读写对象的属性和属性读写异常
- 删除属性
- 检测属性
- 枚举属性
4.1 读写对象的属性和属性读写异常
读写对象的属性可以使用中括号[]或者点号 .
对象属性的查找方式,先找对象自身是否有这个属性,如果没有就顺着原型链向上查找直到找到为止;或者找到null页没有就返回undefined;
另外,对象的属性是字符串类型哦
先来一道题看看你是否理解这个了。答案在本文最后哟~
var a={},b={key:'b'},c={key:'c'};
a[b] = 123;
a[c] = 456;
console.log(a[b]);
// 属性读写 使用中括号或者点号来实现对象的读取
var obj = {x:1,y:2};
obj['x']; // 获取obj对相关的属性x值 1
obj.y; // 获取obj对相关的属性y值 2
obj['x'] = 3; // 给对象的属性赋值
obj.y = 4;// 给对象的属性赋值
//使用for in 遍历属性的值
//会将原型链上的可枚举属性页遍历出来
var p;
for(p in obj){
console.log(obj[p]); //这时候要使用[] 不然代表访问的obj.p属性
}
//读写不存在的属性
obj.z; //undefined
var yz = obj.y.z; // TypeError: Cannot read property 'z' of undefined
obj.y.z = 2; //TypeError: Cannot set property 'z' of undefined
// 为了避免出现这样的错误可以如下操作
var yz;
if(obj.y){
yz = obj.y.z;
}
// 或者使用下面的语句
var yz = obj && obj.y && obj.y.z; //前面的属性存在 才会访问后面的属性 若前面的都为true,则会返回obj.y.z的值
4.2 删除属性
删除对象的属性使用delete ,delete不能删除以下的东东
- 当标签的权限属性configurable为false的时候不可以删除属性
- 不能删除全局变量和局部变量
- 不能删除函数
//delete删除属性 返回布尔值true 代表对象没有这个属性了 false代表对象还有这个属性
delete obj.x; //删除对象的x属性 或者使用delete obj[x]
console.log(obj.x); //再次访问则为undefined
var descriptor = Object.getOwnPropertyDescriptor(Object,'prototype');//获取Object的 prototype属性的标签权限
console.log(descriptor.configurable); // false 其中的configurable属性为false
// delete不能删除全局变量或者局部变量
var globalVal = 1;
delete globalVal; // false
console.log("------------");
(function(){
var localVal = 1;
return delete localVal;
}()); // false
//delete不能删除函数
function fn(){
}
delete fn; //false
(function(){
function fn(){};
return delete fn;
}());// false
4.3 检测属性
使用 in 检测对象是否有属性(也可是原型链上的属性)
使用 hasOwnProperty() 判断属性是否是对象本身的
propertyIsEnumerable() 属性是否可以枚举
// 属性检测
var cat = new Object();
cat.legs = 4;
// 对象是否有这个属性用 in 可以是原型链上属性
'legs' in cat ; //true
'sss' in cat; //false
'toString' in cat //true ,inherit property 继承原型链上的
//判断对象本身的属性
cat.hasOwnProperty('legs'); //true;
cat.hasOwnProperty('toString'); // false
//判断对象的属性是否可枚举
cat.propertyIsEnumerable('legs'); // true
cat.propertyIsEnumerable('toString'); // false
//自定义属性为不可枚举
//使用Object.defineProperty()可以定义属性的权限标签 没有写的默认为false
Object.defineProperty(cat,'price',{enumerable:false,value:1000});
4.4 枚举属性
使用for in来枚举对象的属性
for(p in obj){
console.log(p); //p是对象的属性
}
5 属性的get/set方法
get和set是另一种读写对象属性的方式
var girl={
name: 'cindy',
blog: 'https://blog.csdn.net/qq_36381242',
get age() { // 读取age属性的值的时候会调用这个方法
return new Date().getFullYear()-1997;
},
set age(val) { //给age属性赋值时会调用这个
console.log('Cannot set age to '+val); //Cannot set age to 18
}
}
console.log(girl.age);// 22
girl.age = 18;
console.log(girl.age); // 22
get/set与原型链
// set/get与原型链
function foo(){};
Object.defineProperty(foo.prototype,'z',{get:function(){return 1;}});
var obj = new foo();
console.log(obj.z); // 1 z为原型链上的属性
Object.defineProperty(obj,'z',{value:100,configurable:true});
obj.z; //100 这个时候返回的是obj对象上的z属性
6 属性的权限设置
查看某一属性的属性标签:getOwnPropertyDescriptor(obj,str);obj表示要检查的对象 str表示要检查的属性 返回一个对象;
设置属性标签及值:defineProperty(obj,str,{}) obj表示要修改的对象,str表示要定义的属性,后面的对象定义属性值机标签,没有写的标签默认值为false;
标签解读:
- configurable: 是否可设置标签权限
- enumerable: 是否可以枚举 与for in有关
- value: 属性的值
- writable: 是否可写 修改
var girl = {name: "cindy", age :22};
//getOwnPropertyDescriptor(obj,str);obj表示要检查的对象 str表示要检查的属性 返回一个对象
// 查看某一属性的属性标签
var descriptor = Object.getOwnPropertyDescriptor(girl,'name');
console.log(descriptor);//{configurable: true, enumerable: true, value: "cindy", writable: true}
Object.getOwnPropertyDescriptor(girl,'boyFriend'); // 传入没有的属性时 返回undefined
//defineProperty(obj,str,{}) obj表示要修改的对象,str表示要定义的属性,后面的对象定义属性值机标签,没有写的标签默认值为false
// defineProperty设置属性标签及值
Object.defineProperty(girl,'blog',{
configurable: true,
enumerable: true,
value: "https://blog.csdn.net/qq_36381242",
writable: false});
使用Object.keys(obj) 获取对象上所有的可枚举的属性,返回字符串数组;也可以使用for in遍历对象可枚举的属性;
7 对象的标签
对象的标签有
- [[proto]] 原型标签
- [[class]] 表示对象属于那一个类型
- [[extensible]] 表示属性是否可扩展(增加新的属性)
//判断对象类型
var toString = Object.prototype.toString;
function getType(o){
return toString.call(o).slice(8,-1);
}
toString.call(null);//"[object Null]"
getType(null); // "Null"
getType(undefined); // "Undefined"
getType(1); // "Number" 非对象会先转为对应的包装类型
getType(new Number(1)); // "Number"
typeof new Number(1); //'object'
getType(true); // "Boolean"
与扩展标签相关的方法
- Object.isExtensible(obj); 对象是否可扩展
- Object.preventExtensions(obj);//设置为不可扩展
- Object.seal(obj); //将对象的属性标签configurable都设置为false
- Object.isSealed(obj);//判断对象是否被seal
- Object.freeze(obj);//将属性的所有权限标签设置为false
- Object.isFrozen(obj);// 判断对象是否被冻结
// 与扩展标签相关的方法
var obj = {x:1,y:2};
Object.isExtensible(obj); //true
Object.preventExtensions(obj);//设置为不可扩展
Object.isExtensible(obj); //false
obj.z = 1;
obj.z; //undefined
Object.getOwnPropertyDescriptor(obj,'x');// {value: 1, writable: true, enumerable: true, configurable: true}
Object.seal(obj); //将对象的属性标签configurable都设置为false
Object.getOwnPropertyDescriptor(obj,'x'); // {value: 1, writable: true, enumerable: true, configurable: false}
Object.isSealed(obj);//判断对象是否被seal 返回true
Object.freeze(obj);//将属性的所有权限标签设置为false
Object.getOwnPropertyDescriptor(obj,'x');//
Object.isFrozen(obj);// 判断对象是否被冻结
8 对象的序列化及其他一些方法
对象的序列化可以使用JSON.stringify(obj)方法
反序列化使用JSON.parse(str); str为json字符串
注意事项:
- 属性值为undefined的将不会序列化
- 属性为NaN,Infinity 的会转为 null
- 时间对象 new Date() 会转为UTC字符串表示
json字符串的格式一定要对,不然会出错。
json字符串格式 '{"name":"cindy","age":22}'
最外层是花括号,其中的属性一定要用双引号引起来,最后的属性值后不要跟逗号;
// 序列化
var obj = {x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj); // {"x":1,"y":true,"z":[1,2,3],"nullVal":null}
var obj = {val:undefined,a:NaN, b:Infinity,c:new Date};
JSON.stringify(obj); //{"a":null,"b":null,"c":"2019-10-05T08:22:47.537Z"}
//反序列化
obj = JSON.parse('{"x":1}'); //将json字符串转为对象
//序列化--自定义
// 重写对象里的toJSON方法 当使用JSON.stringify的时候会按照toJSON的规则返回属性的值
obj={
x:1,
y:2,
o:{
o1:1,
o2:2,
toJSON:function(){
return this.o1 +this.o2
}
}
}
console.log(JSON.stringify(obj)); '{"x":1,"y":2,"o":3}'
toString(),valueOf()也是对象上的常见方法
当需要让对象(比如 + obj)的时候 会先查看是有valueOf()方法,如果没有就查看toString()方法,这样就可以获得对象的值
来揭晓答案啦!
a[b] 的值是 456。因为对象的属性是字符串,如果不是字符串的化会转为字符串;
其中 b和c 都是对象会转为字符串"[object Object]"
所以 a[b] 等价于 a["[object Object]"] , a[c] 等价于 a["[object Object]"]
好啦,关于JS对象的基础知识就复习到这里啦~~~