JS高程3:面向对象的程序设计——理解对象
JS中对象的定义:
- (无序)属性的集合
- (无序)值的集合
- (无序)名值对的集合
JS对象是基于引用数据类型来创建的。
JS对象创建的2种方式:
- 传统方式
- 对象字面量
var person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function(){
alert(this.name);
};
对象字面量
var person = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName: function(){
alert(this.name);
}
};
属性
JS定义了属性的特性来描述属性。特性由内部值和包含内部值的一对方括号组成:
[[Enumerable]]
Enumerable为内部值。
JS属性分为2种:
- 数据属性
- 访问器属性
1.数据属性
数据属性包含一个数据值位置。(数据值即上面提到的名值对中的值)
数据属性有4个特性:
[[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特
性,或者能否把属性修改为访问器属性。像前面例子中那样直接在对象上定义的属性,它们的
这个特性默认值为 true。
[[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中那样直接在对象上定
义的属性,它们的这个特性默认值为 true。
[[Writable]]:表示能否修改属性的值。像前面例子中那样直接在对象上定义的属性,它们的
这个特性默认值为 true。
[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,
把新值保存在这个位置。这个特性的默认值为 undefined。
下面来看看几个使用这些特性的实例:
要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty()方法。这个方法
接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符(descriptor)对象的属
性必须是: configurable、 enumerable、 writable 和 value。
var person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
alert(person.name); //"Nicholas"
person.name = "Greg";
alert(person.name); //"Nicholas"
上面writable特性被设置为了false,即数据值不能够被修改。
var person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
alert(person.name); //"Nicholas"
delete person.name;
alert(person.name); //"Nicholas"
上面configurable特性被设置为false,即不能够删除属性。
注意:尽量不要设置这些特性,尤其是configurable特性,因为一旦configurable为false,就无法再设置这些特性了。
2.访问器属性
访问器属性有4个特性:
[[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特
性,或者能否把属性修改为数据属性。对于直接在对象上定义的属性,这个特性的默认值为
true。
[[Enumerable]]:表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,这
个特性的默认值为 true。
[[Get]]:在读取属性时调用的函数。默认值为 undefined。
[[Set]]:在写入属性时调用的函数。默认值为 undefined。
访问器属性不包含数据值,只能通过Object.defineProperty() 来定义:
var book = {
_year: 2004,
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;
alert(book.edition); //2
上面,_year表示数据属性,在前面加上下划线,表示只能通过方法来访问该属性。
year表示访问器属性,访问器属性包含getter和setter函数。getter 函数返回_year 的值, setter 函数通过计算来确定正确的版本。
将year属性设置为了2005,会去调用setter函数接收2005并将_year设置为2005,然后edition值也会修改为新值。
注意:只指定getter函数,意味着属性只读;只指定setter函数,意味着属性不能读。
早期时候的实现方法:
var book = {
_year: 2004,
edition: 1
};
//定义访问器的旧有方法
book.__defineGetter__("year", function(){
return this._year;
});
book.__defineSetter__("year", function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
});
book.year = 2005;
alert(book.edition); //2
注意:在 不 支 持 Object.defineProperty() 方 法 的 浏 览 器 中 不 能 修 改 [[Configurable]] 和[[Enumerable]]。
定义多个属性
由于经常需要为对象定义多个属性,所以ECMAScript 5定义了Object.defineProperties()方法。
这个方法接收两个对象参数:第一
个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象中要添加或修改的属性一一对
应。例如:
var book = {};
Object.defineProperties(book, {
_year: {
value: 2004
},
edition: {
value: 1
},
year: {
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
以上代码在 book 对象上定义了两个数据属性(_year 和 edition)和一个访问器属性(year) 。
读取属性的特性
使用 ECMAScript 5 的 Object.getOwnPropertyDescriptor()方法,可以获取给定属性的描述
符对象。这个方法接收两个参数:属性所在的对象和要读取其描述符对象的属性名称。
var book = {};
Object.defineProperties(book, {
_year: {
value: 2004
},
edition: {
value: 1
},
year: {
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
alert(descriptor.value); //2004
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined"
var descriptor = Object.getOwnPropertyDescriptor(book, "year");
alert(descriptor.value); //undefined
alert(descriptor.enumerable); //false
alert(typeof descriptor.get); //"function"
注意:在 JavaScript 中,可以针对任何对象——包括 DOM 和 BOM 对象,使用 Object.getOwnPropertyDescriptor()方法。
最新文章
- 常用的SQL语句
- JsonFormatter PrettyPrint
- LR检查点的if (status == LR_FAIL)写法
- STM32学习笔记(五) USART异步串行口输入输出(轮询模式)
- codeforces A. Bayan Bus(简单模拟)
- 怎样写 OpenStack Neutron 的 Extension (一)
- 关于eclipse中maven项目的问题
- js调试-定位到函数所在文件位置
- Day 16: Goose Extractor —— 好用的文章提取工具
- 剑指offer 连续子序列和
- virtualbox+ievms:还你一个原装IE8
- Nodejs全局安装和本地安装的区别
- 3070 Fibonacci
- java多线程系列11 juc包下的队列
- 【Java基础】11、java方法中只有值传递,没有引用传递
- 【转】CentOS 7.X 系统安装及优化
- canvas 实现弹跳效果
- 树莓派进阶之路 (018) - raspberryPi摄像头命令行软件raspistill帮助文档
- 前端js如何生成一个对象,并转化为json字符串
- 公司里面用的iTextSharp(教程)---生成一个简答的PDF的语法
热门文章
- Linux makefile 教程
- juqery.fn.extend和jquery.extend
- dl,dt,dd标记在网页中要充分利用
- iOS:tableView表头下拉放大的效果
- window环境下备份与恢复(实际操作)
- 跟着我从零开始入门FPGA(一周入门XXOO系列)-1、Verilog语法
- DevExpress 中 汉化包 汉化方法
- Struts2中的页面跳转
- MongoDB之Map-Reduce -- Mongo Shell版和C#版(上)
- vue 不能监测数组长度变化length的原因