对象
-
创建对象
1) 对象直接量:var obj1={}
2) new 关键字:var obj2=new Object()
3) Object.create()函数:var obj3=Object.create(prototype) //prototype是想要创建的对象的原型对象。
eg:var obj4=Object.create(Array.prototype)
创建一个数组对象,此时的obj4继承了数组对象的所有方法和属性;
相反,如果参数填一个null对象,那么会创建一个新的空对象,但是它不会继承任何的属性或方法:var obj4=Object.create(null)。
2. 对象属性及访问
1) 属性
对象是由一系列的“属性名:属性值”的键值对组成的由花括号{}包裹起来的变量。
其中的属性名,也叫作键名,可以是任意的原始类型:字符串(包括空字符串),数字,布尔值,null,undefined;属性值可以是任意的数据类型,包括对象类型。
{ aa: null, bb: undefined, childern: {child1: "111"}, null: 2, sebling:[1,2,3,4], true: 1, undefined: 3, 1: 111 }
2) 属性的访问
属性访问有两种方式:“对象.属性名”和“对象[属性名]”。
使用“.”的时候,属性名只能是一个标识符(可看做不加“”的字符串):obj.aa,如果属性名是数字或空字符串,不能写成obj.1和obj.””,而是写成方括号形式,即obj[1]、obj[“”]。
* 在使用方括号的时候,我们说方括号里只能返回字符串。严格来说,方括号里只能是可以转换成字符串的值。
直接访问一个不存在的属性是不会报错的,会返回undefined,但间接访问一个不存在的属性则会报错。比如obj={},访问obj.name的时候返回undefined,访问obj.name.length的时候则会报length is undefined的错误。原因是obj.name已经是undefined了,undefined没有length属性。处理方法(最直接,最简洁):obj&&obj.name&&obj.name.length,返回的是undefined,而不会报错。
3) 作为关联数组的对象
普通的数组,我们在访问它的数组项的时候,都是通过数字索引值来访问的:arr[1],关联数组就是通过字符串索引来访问数组项的数组:arr[“1”]、arr[“aaa”],也称为散列、映射或字典。
javascript里的对象都是关联数组。
当对象的属性名不确定时,必须使用方括号来访问,因为方括号里返回的字符串是动态的,在运行过程中可以更改,所以可以用一个变量来接收这个字符串值,然后方括号里使用这个变量,就可以访问这个不确定的属性的值了。
4) 继承
对象的属性一部分是自己本身的属性,另一部分可以是从原型链上的对象继承而来。当访问对象obj的x属性时,如果obj本身就有x属性,那就直接返回x的值;如果obj没有x属性,那么就在他的原型对象身上去找是否有x属性,有就返回这个值,没有就继续在obj的原型对象的原型对象身上去找......以此类推,直到找到x或者找到一个原型是null的对象为止,有就返回该值,没有就返回undefined。可以看到,对象的原型的属性构成了一个“链”,对象通过这条“链”来实现属性的继承。
5) 属性赋值
属性赋值首先要检查原型链,如果允许进行赋值操作,也总是在原始对象上创建属性或对已有属性进行赋值,而不会去更改原型链上的属性值。
在JavaScript中,只有在查询属性的时候才能体会到继承的存在,属性赋值跟继承无关。
6) 删除属性
删除属性用“delete”。
delete的一般用法是delete + 对象.属性名:delete obj.name。delete只能删除自身属性,不能删除继承属性。
delete表达式如果删除成功或者无副作用时,会返回true;如下情况都返回true:
delete obj.gender 删除obj的gender属性,返回true
delete obj.gender obj.gender已经不存在,什么也不做,返回true;
delete obj.toString 删除继承属性,无效,什么也不做,返回true;
delete 1 表达式无意义,什么也不做,返回true
delete 不能删除那些可配置性为false的属性,比如内置对象的prototype、全局var 变量、全局函数等:
delete Object.prototype 不可删除,属性不可配置,返回false;
var a=1;delete a; var变量是不可配置变量,此处a不可配置,不可删除,返回false;
function f(){};delete f; 全局函数不可删除,返回false;
创建一个可配置的全局变量或方法时,delete表达式返回true,可删除:
this.b=1;delete b; 可删除,返回true;
this.f1=function(){};delete f1; 可删除,返回true
7) 检测属性
var obj = {name:’123’,age:123,x:undefined}
检测属性可以用“in”运算符、hasOwnPropoerty方法、propertyIsEnumberable方法、Object.getOwnPropertyNames方法以及“!==undefined”来实现。
* in运算符可以识别undefined和null,但是不会区分自身属性与继承。注意需要检测的属性名要加””,否则它表示的是一个变量,变量 in 对象,返回false:
“name” in obj; //name存在于obj中,返回true;
“x” in obj; //true
“toString” in obj; //true
name in obj; //false
“sex” in obj; //false,obj中不存在sex属性
* hasOwnProperty方法也可以识别undefined和null,同时会区分自身属性与继承属性(属性记得加””):
obj.hasOwnProperty(“name”); //true
obj.hasOwnProperty(“x”); //true
obj.hasOwnProperty(“toString”); //false toString是继承属性,返回false
obj.hasOwnProperty(“sex”); //false,obj中不存在sex属性,返回false
* propertyIsEnumberable 方法是 hasOwnProperty 的强化,在hasOwnProperty方法的特性下,还可以区分可枚举属性和不可枚举属性。有些内置对象的属性是不可枚举的,通常用JavaScript创建出来的属性是可枚举的。
obj.propertyIsEnumberable(“name”); //true
obj.propertyIsEnumberable(“x”); //true
Object.prototype.propertyIsEnumerable('toString'); //false
*Object.getOwnPropertyNames 方法获取自身的属性,而且能获取到可枚举值为false的属性:
var obj = {name:’ll’,age:21};
Object.defineProperty(obj,’x’,{value:’123’,enumberable:false})
Object.getOwnPropertyNames(obj); // [‘name’,’age’,’x’]
* 除了用“in”运算符判断属性是否为undefined外,“!==”也可以区分undefined 和 null,“!==”的左右两边要求值和类型都必须一致时才返回true,而“!=”仅仅是值等就可以返回true。
* 对象属性的可枚举性:属性的可枚举性是通过定义属性的defineProperty方法中的enumberable属性来确定的,如果某个属性的enumberable的值定义为false,那么 for/in 、Object.keys()以及JSON.stringify()都不能遍历到该属性。
Object.defineProperty(obj,"sex",{value:"女",enumberable:false})
Object.keys(obj); //["name", "x",”age”]
JSON.stringify(obj); //"{"name":"123",age:123}" //JSON.stringify()也不能识别值为undefined的属性
8) 属性的setter和getter
如果只有getter,那么getter的那个属性是只读,如果既有getter又有setter那么该属性是可读写的。setter属性必须要有一个参数。
var obj1 = { x:1, y:2, get sum(){return this.x+this.y}, set sum(newvalue){ this.x += 1; this.y += 1; } // 作用???? } obj1.sum // 3