- 对象是JavaScript基本的数据类型,它是一种复合值或者属性的无序集合。
- JavaScript对象可以从原型对象中继承属性,对象的方法通常是继承的属性。
- JavaScript对象是动态的,可以删除和增加属性。
- 名:包含空字符串在内的任意字符串
- 值:任意的javascript值/getter和setter函数
属性特性
- 可写 ——是否可以设置该属性的值
- 可枚举——是否可以通过for/in循环返回该属性
- 可配置——是否可以删除或修改该属性
- 对象的原型:指向另外一个对象,本对象的属性继承自它的原型兑现。
- 对象的类:标志对象类型的字符串。
- 对象的扩展标记:指明了是否可以向该对象添加新的属性。
JavaScript的三类对象
- 内置对象——由ECMAScript规范定义的对象或者类(数组、函数、日期)。
- 宿主对象——由JavaScript解释器所嵌入的宿主环境定义。
- 自定义对象——由运行的JavaScript代码创建的对象。、
- 自有属性——直接在对象中定义的属性。
- 继承属性——在对象的原型对象中定义的属性。
var empty = {};
var point = { x:0, y:0 };
var point1 = { x:point.x, y:point.y };
var book = {
"main title":"javascript",
"sub-title":"guide",
author:{
firstname:"David",
surname: "Flanagan"
}
}
2.通过new创建对象
new运算符创建并初始化一个新的对象,new后面跟随一个构造函数。(javascript的原始类型都有自己的构造函数)
var o = new Object();
var a = new Array();
var d = new Date();
var r = new RegExp("js");
除了这些内置的构造函数,自定义构造函数也可以用来初始化新对象。
3.Object.creat()
通过Object.creat()方法来创建一个新的对象。该方法具有两个参数:第一个参数是这个对象的原型,第二个参数是可选的,对对象的属性进行描述。
(Object.creat()是一个静态函数,不能被某个对象调用。)
var o = Object.creat({x:1,y:2});//继承了属性x和y
这个方法也可以传入null作为参数,但是这个对象将不会继承任何属性或者方法。
var o1 = Object.creat(null);//不继承人任何属性
如果想创立普通的空对象,必须传入Object.prototype来获取对原型的引用。
var o2 = Object.creat(Object.prototype);
//等价于
var o2 = {};
//等价于
var o2 = new Object();
可以通过任意原型来创建新对象,使任意对象都可以被继承。通过继承,给继承的属性赋值,只会改变继承对象的本身而不会对原始对象造成修改。
通过原型继承来创建一个新的对象
/*
* 通过原型继承创建一个新对象
*/
//inherit()返回了一个继承自原型对象p的属性的新对象
//如果存在Object.create()方法,如果没有则使用其他方法
function inherit(p) {
if(p == null) throw TypeError();
if(Object.create){
return Object.create(p);
}
var t = typeof p;
if(t != "Object" && t != "function") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
二.属性的查询和设置
通过(.)或者([ ])来获取属性的值。方括号内可以是计算结果为字符串的表达式。
区别:通过(.)来访问对象属性时,属性名是一个标志符,标志符不是数据类型,因此程序无法修改它。
通过([ ])来访问,属性名是一个字符串,所以可以修改和创建它们。
属性值是关键字或者保留字,则用o["for"]这种形式进行保留。
1.作为关联数组的对象
关联数组——通过字符串索引而不是数字索引。(又称散列、映射、字典)。
JavaScript对象都是一种关联数组。
2.继承
JavaScript对象具有自由属性,也有一些属性是从原型对象继承来的。
var o ={} //o是从 Object.prototype继承对象的方法
o.x = 1; //给o定义一个属性x
var p = inherit(o); //p继承o和Object.prototype
p.y = 2; //给p定义一个属性y;
var q = inherit(p) //q继承p、o和Object.prototype
q.z = 3;
var s = q.toString() //toString继承自Object.prototype
var a = q.x + q.y;
通过原型链来实现属性的继承。
给对象o的属性x赋值
- 如果o中已有x属性,赋值操作改变x的值。
- 如果o中没有x属性,则新增一个属性。
- 如果o中属性是继承过来的,这个继承属性被新创建的的同名属性覆盖,并且被继承原型中的x属性不发生改变。
var unitcirle = { r:1 };
var c = inherit(unitcirle);
c.x = 1, c.y = 1;
c.r = 2;
unitcirle.r;//1
3.属性访问错误
- 查询一个不存在的属性并不会报错。
- 如果对象不存在,查询属性就会报错。
- 给null和defined设置属性也会报类型错误。
- o中的属性p是只读的。
- o中的属性p是继承且只读的。
- o中不存在自有属性p:p没有使用setter方法继承属性p,并且o的可扩展性是false。
delete表达式删除成功或者没有任何副作用时,返回true,或者delete后面跟的不是属性访问表达式,同样返回true。
o = { x:1 };
delete o.x;//删除成功 返回true
delete o.x;//什么都没做 返回true
delete o.toString; //无法删除继承属性,返回true
delete 1; //无意义 返回true
delete不能删除可配置性为false的属性
var x = 1;//声明一个全局变量
delete this.x; //不能删除这个属性
function f() {} //声明一个全局函数
delete this.f;//不能删除这个函数
四.检测属性通过in运算符、hasOwnPreperty()和propertyIsEnumerable()方法来完成。
in运算符的左边是属性的名,以字符串的形式
"x" in o; //true
"y" in o;//false
"toString" in o;//true
hasOwnPreperty()用来检测是否为对象的自有属性。 o.hasOwnPreperty("x");
propertyIsEnumerable()在检测自有属性的基础上,再检测这个自有属性的可枚举性。
除此之外 还可以用 o.x !== undefined来检测属性。(in可以区分不存在的属性和存在但值为undefined的属性)
五..枚举属性
对象属性可枚举,就是该对象的属性值不可修改,是个常量。
for/in循环是遍历对象中所有可枚举的对象。(包括自有属性和继承属性)
var o = {x:1, y:2, z:3};
for(p in o) //遍历属性
console.log(p); //输出x y z
Object.prototype添加了新方法和属性,并被所有对象继承和使用,但是在ES5标准之前是被定义为可枚举的属性,所以在遍历属性时要对这些属性进行过滤。
//过滤掉继承Object.prototype的属性
for(p in o){
//跳过继承的属性
if(!o.hasOwnProperty(p))
continue;
}
for(p in o){
//跳过方法
if(typeof o[p] === "function")
continue;
}
ES5定义了两个枚举属性的函数:
- Object.keys()——返回一个有可枚举的自有属性的名称组成的数组。
- Object.getOwnPropertyNames()——返回对象所有自有属性的名称,不仅仅是可枚举的属性。
六.属性getter和setter
属性值可以用getter和setter这两个方法替代。有这两个方法定义的属性——存取器属性。
//对象直接量属性定义存取器属性
var o = {
//普通的数据属性
data_prop: value,
//存取器属性都是成对定义的函数
get accessor_prop() {},
set accessor_prop(value) {}
}
- 属性名相同的函数。
- 函数体内this指对象。
- 存储器属性是可以继承的。
七.属性的特性
- 可写
- 可枚举
- 可配置