【JS】JavaScript理解对象:属性类型
JavaScript高级程序设计第三版 139页 Object.defineProperty()函数:
Object.defineProperty()方法接收三个参数,属性所在的对象,属性的名字和一个描述符对象。其中描述符对象的属性必须是:configurable,writeable,enumerable,value。设置其中一个或多个值,可以修改对应的特性值。
JavaScript高级程序设计第三版 139页 数据属性:
数据属性包含一个数据值的位置。在这个位置可以读取和写入值
javascript
var person = {
name : "Nicholas"
}
//第一个问题:
//这里面的name属性是数据属性?
JavaScript高级程序设计第三版 141页,访问器属性:
访问器属性不包含数据值
javascript
var book = {
_year : 2004,//_year前面下划线是常用的记号,表示只能通过对象方法访问的属性
edition : 1
};
Object.defineProperty(book,"year",{
get : function () {
return this._year;
},
set : function (newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
//第二个问题:上行代码为什么没有给book新添加一个year属性?
//第三个问题:
//如果上行代码注释掉,alert(book.year)为undefined。不注释的话alert(book.year)警告框显示2005. 可是book中并没有添加一个year属性,为什么在执行上一行代码以后便可以alert了?弹出的值是_year的值,证明book.year访问的是_year了吧?_year不是只能通过对象方法访问么?为什么直接alert(book.year)便可以访问了?
回答
name
是数据属性。书上说数据属性包含一个数据的位置。在这个位置可以读取和写入值。言下之意即,数据属性是可以直接通过对象.属性
的形式访问和赋值的。题中name
可以这样做。所以它是一个数据属性。通过
Object.defineProperty()
方法,可以创建数据属性(并设定其[[Enumerable]]等内部属性),也可以创建访问器属性(访问器属性仅包含getter
和setter
函数,当然这两个也不是必须的)。第二问中这样的创建方式即创建了book
对象的访问器属性,而非数据属性.- 接第二点,
year
(当然名字可以自定义,随便取)是book
对象一个访问器属性。直接调用book.year
,即调用了这个访问器属性中定义的get
方法,返回book._year
这个数据属性。如果给book.year
赋值,就是调用了这个访问器属性中定义的set
方法。楼主可以在get
和set
方法体中分别加入console.log("某个字符")
,这样的代码,再调用book.year
或给其赋值,应该就明白了。数据属性不仅可以直接访问,也可以通过定义的访问器来专门访问。P.S. 可以在浏览器的控制台中打印
book
对象,你会发现是这样的:
楼上已经说的很明了了,我在补充一点。javascript
一共用三种属性
普通属性
(也就是楼主说的数据属性), 这种属性是用户赋给它们,它们就返回什么,不会做额外的事情var person = {
name : "Nicholas"
}
alert(person.name) // "Nicholas"
内部属性
,比如数组的length
属性,函数的prototype
属性, DOM
节点的innerHTML
属性,用户对它们进行赋值后, 再取值时,它不一定按我们的预期做事,此外还会做一些格外的事情。另外,我们也很难改变它们的行为。 比如说某一数组,它的长度为10, 当我们设置它为11时,它就会增加一个undefined
元素,再设置为9时,就会从后面删掉两个元素。 函数的prototype
如果被改变,相当于将其父类改变了,会new
不同类型的实例。 DOM
的innerHTML
,我们赋值时是一个字符串,再取出时,这字符串可能会与原来的不一样, 并且在原元素上生成了不一样的子节点。
访问器属性
,允许用户在赋值或取值都经过预先设定的函数,从而实现内部属性的那一种特殊效果。
第一个问题:是数据属性。
第二个问题:book.year = 2005; Object.defineProperty给book的_year属性新建一个名字year。
第三个问题:_year : 2004;表示book就有一个_year属性,js本身没有访问控制功能,你可以试试alert(book._year)一样可以访问
其实你再往后面看看章节 6.1.2 定义多个属性
所用的 Object.defineProperties()
方法重写上面的例子,可以知道数据属性和访问器属性是同级别的关系,只是由于功能不同把它们分成两派,按照它们所谓的 “特征值” 定义这个属性的性质。访问器属性只是因为它带有可以访问对象内其它属性(比如作为数据属性中[[Value]]的值,即上面例子中 _year
的值)的功能(通过 getter、setter 函数),并经过一些处理(例子中的 get、set 内的处理)从而实现 “设置一个属性的值会导致其他属性发生变化”(高程原话)的效果,即 book.year
影响 book._year
。
第一个问题:name
属性是数据属性,因为这个属性带有所谓的“特征值”[[Value]]
:包含这个属性的数据值。
第二个问题:year
作为参数传入方法中,这样方式即创建了 book 对象的访问器属性 year
,但它不是数据属性(访问属性不包含数据值),不同显式写出来。而 book.hasOwnProperty("year");
确实返回 true
。
第三个问题,可以这样理解,Object.defineProperty(book,"year",{...});
返回了设置后的 book
对象。
var book = { _year : 2004,//_year前面下划线是常用的记号,表示只能通过对象方法访问的属性
edition : 1
};
Object.defineProperty(book,"year",{
get : function () {
return this._year;
},
set : function (newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
我想问下,这个_year 属性,上面说的是只能通过对象方法访问,但是我在下面直接也能访问和修改,
请问这样写 _year 属性,是什么用法?表达的是规则还是一种可行性?
以上是 【JS】JavaScript理解对象:属性类型 的全部内容, 来源链接: utcz.com/a/84297.html