JavaScript对象的属性分两种,一种是自己定义的,被称为“自有属性”。也有一些属性是从原型对象继承过来的。对象属性的多继承关系构成了原型链。
对象属性在赋值前会先检查原型链,以此判断是否允许赋值操作。例如,如果对象o继承自一个只读属性x,那么对x属性赋值是不允许的。如果允许属性赋值,也只是在原始对象上创建或对已有的属性赋值,而不会修改原型链。
JavaScript中,一般只有在查询属性的时候才能体会到继承的存在,而设置属性和继承无关。通过这个特性可以有选择的覆盖继承的属性。
属性访问错误
查询一个不存在的属性不会报错。如果在对象自身属性和继承的属性中没有找到指定属性,则返回undefined。通过下面一小段代码验证下:
var a = { name: 'admin' }; //定义一个原型对象a var b = Object.create(a); //定义一个对象b继承至对象a console.log(b.name); //=> admin b继承a的name属性,正常输出 console.log(b.age); //=>undefined b本身和继承对象都没有age属性,故输出undefined
但有一种情况:假如对象不存在,试图访问这个不存在对象的属性时则会抛异常。例如:
console.log(c.name); //Uncaught ReferenceError: c is not defined var d = null; console.log(d.name); //Uncaught TypeError: Cannot read property 'name' of null
所以,这就要求我们在访问不确定对象属性时需要验证一下。
var book = { "length": 21 }; var len = book && book.length; //这里用&&的第三种用法代替if。 console.log(len); //=>21
3.删除属性
delete运算符可以删除对象的属性,删除成功返回true。但是delete不能删除那些可配置型为false的属性。只能删除自身属性,不能删除继承属性。
delete book.author // 返回true
删除全局属性时,可以直接省略全局对象,delete后面跟上要删除的属性即可。
this.x=1; //创建一个全局属性 console.log(delete x); //=>true
4.检测属性
所谓检测属性就是判断某个属性时候存在与某个对象中。一般可以通过in运算符、hasOwnProperty()和propertyIsEnumerable()方法来完成验证工作。
in运算符判断,如果对象自有属性或继承属性包含这个属性则返回true。
var o = { "x": 5 }; console.log("x" in o); //=>true 对象o有属性x console.log("y" in o); //=>false 对象o没有属性x console.log("toString" in o); //=>true 对象o继承属性toString
hasOwnProperty()方法用来检测给定属性是否为对象的自有属性,对于继承属性返回false。
var o = { "x": 5 }; console.log(o.hasOwnProperty("x")); //=>true console.log(o.hasOwnProperty("toString")); //=>false
propertyIsEnumerable()方法是hasOwnProperty()的增强版。只有检测到属性为对象的自有属性并且这个属性可枚举性时才返回true。
var o = Object.create({ "y": 5 }); o.x = 6; console.log(o.propertyIsEnumerable("x")); //=>true x为自有属性 console.log(o.propertyIsEnumerable("y")); //=>false y是继承属性 console.log(Object.prototype.propertyIsEnumerable("toString")); //=>false toString不可枚举
5.属性存取器
ECMAScript 5版本中,对象可以用get和set关键字定义像C#、Java等高级语言一样的保护属性。这种属性被称为“存取器属性”,它是可以继承的。
var obj = { //数据属性(可看成字段) data: null, //存取器属性(保护属性) get Data() { return this.data; }, set Data(value) { this.data = value; } }; obj.Data = "admin"; console.log(obj.data); //=>admin
怎么样,有没有感觉和JAVA中的保护属性写法很像。因为JavaScript本身就是一种面向对象的编程语言。
如果对象属性同时具有get和set方法,那么它是一个可读/写的属性。如果属性只有一个get方法,那么它是一个只读属性。如果属性只有一个set方法,那么它是一个只写属性,读取只写属性总是返回undefined。
6.属性的特性
ECMAScript 3版本下对象的属性都是否可写、可配置和可枚举的,但是到ECMAScript 5版本下是属性是可以通过一些API来标识是否为可写、可配置和可枚举的。这API也就是所谓的属性的特性。
普通数据属性的4个特性:value(值)、writable(可写性)、enumerable(可枚举性)、configurable(可配置性)。
存储器属性的4个特性:get(读取)、set(写入)、enumerable(可枚举性)、configurable(可配置性)。
ECMAScript 5中定义了一个Object.getOwnPropertyDescriptor()方法用来查询对象特定属性的特性,返回一个“属性描述符”对象,该对象就代表对象属性的4个特性。