1、什么是对象?为什么要面向对象设计程序?
ECMA-262把对象的定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”面向对象的程序设计时,一个对象可以包含很多相似的内容,将类似的功能全部设计在一个对象里面。
写程序就像商业区规划一样,一个对象的作用就像一栋楼一样,这栋楼全是服装店,这栋楼全是超市,那栋楼全是影院,假如没有楼,就会出现这家超市旁边有服装店,会变得杂乱无章。这个简单的比喻就知道,面向对象设计会程序变得更加简洁,也更容易维护,架构也会更加清晰。
2、JS的对象的表现形式?如何创建一个对象?
JS里面除了基本数据类型(简单的数据段如:Undefined、Null、Boolean、Number和String,此处不太严谨,但是不做过多讨论),其余均是对象,例:函数是对象,数组是对象,“对象”是对象,可谓“万物皆对象”。
最常见:定义一个引用类型数据、函数或数组均相当于创建了一个对象。
最常用:按照对象定义,利用Object()创建一个示例,然后添加相应属性和方法。例如:
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);
}
};
二者若用在对象初始化时,没有任何区别,但是若对象本身已经存在某些属性或方法,前者只会增加或者更换对应的属性(若同名),而字面量方法则会覆盖掉原先的所有对象属性。(此处用覆盖不太严谨,确切来说是对象名称这个指针会指向新的那个字面量定义的对象,而旧的则会被释放等待垃圾回收)。
3、对象有什么属性?
重复说明:对象是一个包含属性、方法或者另一个对象的集合。这里对象包含的每一个部分或者称为“自定义属性”都有以下几个内部的属性(为实现JavaScript引擎用,实际开发不常用):
这部分属性JavaScript无法直接访问,为区别与普通属性,常用双括号括起,例:[[Enumerable]]。
这里先介绍JS一个用于操作内部属性的方法:Object.defineProperty()。该方法需接受三个参数:属性所在对象,属性的名字和一个描述对象。
a、数据属性(JS无法直接访问,不可直接修改,必须使用ECMAscript 5的Object.defineProperty()来实现):
属性 | 作用 | 自定义属性默认值 |
configurable | 1、能否通过delete 删除属性从而重新定义属性 2、能否修改属性的特性 3、能否把属性修改为访问器属性 | true |
enumerable | 能否通过for-in 循环返回属性 | true |
writable | 能否修改属性的值 | true |
value | 1、包含这个属性的数据值 2、读取属性值的时候,从这个位置读 3、写入属性值的时候,把新值保存在这个位置 | 该属性默认值为:undefined |
修改数据属性示例:
var person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
alert(person.name); //"Nicholas"
person.name = "Greg";
alert(person.name); //"Nicholas"
注:一般情况下可多次调用Object.defineProperty()方法修改同一个属性。但是有例外:在将Configurable属性置为false之后,再调用Object.defineProperty()方法修改除writable 之外的特性,都会导致错误。
定义一个对象,内部的自定属性的数据属性默认都为true,但是,在调用 Object.defineProperty()方法去定义一个在对象里不存在的新属性时,该属性对应的数据属性如果不指定,configurable、enumerable 和writable 特性的默认值都是false。例:
obj = {test1: 123};
Object.defineProperty(obj, 'test2', {value: 110});//当做方法去定义一个新的属性的数据属性
Object.getOwnPropertyDescriptor(obj, 'test1'); // Object {value: 123, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(obj, 'test2'); // Object {value: 110, writable: false, enumerable: false, configurable: false}
b、访问器属性(不可直接定义,必须使用Object.defineProperty()定义):
属性 | 作用 | 自定义属性默认值 |
configurable | 同上 | true |
enumerable | 同上 | true |
get | 读取属性时调用的函数 | undefined |
set | 写入属性的时调用的函数 | undefined |
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;
alert(book.edition); //2
注:在设置访问器属性的时候不一定要同时设置getter和setter。若只设置getter意味属性只可以读不可以写。兼容性解决方案:__defineGetter__()和__defineSetter__()。
4、如何去定义多个属性(内部属性)?
ECMAScript 5提供一个方法来解决这个问题:Object.defineProperties()。该方法允许通过描述符一次定义多个属性。
两个对象参数(两个参数,都是对象类型):1、要添加和修改其属性的对象;2、包含前者对象中要添加或修改的属性的对象
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)。最终的对象与之前定义的对象相同。唯一的区别是这里的属性都是在同一时间创建的。
5、如何读取对象的属性值?
使用 ECMAScript 5 的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。
两个参数:1、属性所在的对象;2、要读取其描述符的属性名称
返回值:一个对象:①若是访问器属性,这个对象的属性有configurable、enumerable、get 和set;②若数据属性,这个对象的属性有configurable、enumerable、writable 和value
//接上面定义的对象
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.getOwnProperty-
Descriptor()方法。