JavaScript是一种弱类型语言,并没有类的概念,但江湖有传闻说“万物皆对象”。所以JavaScript就用对象的形式,从逻辑上实现了面向对象编程。
对象理解
对于诸如java这种强类型语言来说,对象即为class
,但是JavaScript不存在class
。如前所述,万物皆对象,因此JavaScript的面向对象实现,采用了Object
。
对象创建
我们都知道,对象一般都存在属性
和方法
。那么JavaScript对象也不能免俗,只是实现起来更简单粗暴。如下:1
2
3
4
5
6
7var myObject = {};
myObject.name = "object";
myObject.sayName = function(){
return this.name;
}
var object = new myObject();
console.log(object.sayName());//输出this.name的值为object
上面的代码就定义了myObject
对象,同时给对象定义了name
属性和sayName
方法。
但是上述代码创建的对象存在一些问题。首先,只是在逻辑上实现了面向对象,但是并不正存在所谓的myObject
类型,即instanceof(object)!="myObject"
返回值为false
;其次,类中的sayName
方法在每次调用的时候都会重新创建,此方法定义等价于myObject.sayName = new Function()
。当使用new
关键字时,意味着每次调用该方法,就会重新开辟内存,没有实现类方法的共享。
解决第一个问题只需要通过如下方式创建对象:1
2
3
4
5function newObject(){
this.name = "new object";
}
var newobject = new newObject();
console.log(instanceof(newobject));//输出newObject
解决第二个问题,则需要使用对象的原型
属性。对象的原型属性,可以被所有实例共享。1
2
3
4
5
6
7
8
9
10
11function newObject(name,age){
this.name = name;
newObject.prototype.age = age;
newObject.prototype.sayInfo = function(){
return this.name+"的年龄是"+this.age;
};
}
var newobject1 = new newObject("new object1",23);
var newobject2 = new newObject("new object2",33);
console.log(newobject1.sayInfo());//new object1的年龄是33
console.log(newobject2.sayInfo());//new object2的年龄是33
你没看错,上述定义了对象newObject
的两个实例,其中定义时输入了不同的age
,但是,调用sayInfo
方法时,输出年龄相同。这是因为age
属性是原型属性,即为所有实例共享。当声明newobject1
时,age
的值为23
,因为age
属性所有实例共享,所以声明newobject1
时,新传入的age
值会覆盖原有值。
通过如上方法创建类,我们发现可以通过原型
实现方法的共享,同时实例的特有属性值,应避免通过原型进行定义。
属性类型
通过JavaScript的对象实现的类,为了保证类的完整性和安全性,需要对类的属性类型进行控制。类的属性常用类型有以下三种,分别为:
- Configurable:表示能否对属性进行修改(注:删除也是修改)
- Enumerable:表示能否通过
for-in
循环返回属性 - Writable:表示能否修改类的值
属性定义常用方法如上述创建类一样,可直接定义。直接定义的属性上述类型值均为true
。如果需要对属性值进行特殊限定,可使用Object.defineProperty()
进行限定,通过该方法进行限定之后,上述类型的默认值为false
。该方法接受三个参数,第一个参数为类名,第二个参数为属性名,第三个参数为属性类型。1
2
3
4Object.definePropety(newObject,"address",{
configurable:true,
value:"china"
});
总结
JavaScript面向对象实现起来比较简单,但是细节问题很多,要想能熟练应用,需要对原型链相关知识点进行学习,原型链时实现JavaScript面向对象的重要特性,后续的继承实现全部依靠原型链完成。