javascript中的对象
在javascript的学习中,要说最难理解的一部分应该就是对象了。javascript是一门面对对象的语言,但js中的对象又和java和c++这种传统面对对象的语言有所不同,在js中你所遇到的所有东西都可以归为对象。
甚至在js中都没有类的语法定义,而是通过对象来封装属性和方法,并且使用原型对象创建实例对象。
故我在此总结下对象创建的一些方法,也方便以后复习查阅
一.命名空间模式
js中的命名空间通常可以用来减少全局变量的数量,从而有效避免命名冲突。具体的实现方法就是创建一个全局的对象,然后将所要申明的属性和方法都添加到这个对象上,从而避免到处申明全局变量和全局方法。这种方法也被称为对象字面量模式。例如:
//global object
var myObject1 = {};
myObject1.name = '';
myObject1.data = function() {};
//global object
var myObject2 = {
name: '',
data: function() {}
};
以上,我定义了两个全局对象myObject1, myObject2并且简单的封装了一个属性和一个方法。当我们要生成实例的时候,可以
var myobject = {};
myobject.name = 'foo';
myobject.data = function() {
console.log(this.name);
};
这样虽然实现了对象的创建,但缺点也是显而易见的。首先,我们所创建的实例对象和原型对象之间看不出任何关系(从这种意义上来看,原型对象甚至是多余的),其次,我们每次创建一个新的实例对象的时候,语法都过于麻烦。
二.构造函数模式
javascript原生提供了一个构造函数模式用于原型对象生成实例对象。构造函数的申明和普通函数一样,但在内部使用了this变量,并且通过new关键字调用构造函数来生成实例。例如:
//constructor
function Animal(name, words) {
this.name = name;
this.specis = 'dog';
this.words = words;
this.bark = function() {
console.log(this.words);
}
}
//object
var dog = new Animal('dog', '汪汪汪');
console.log(dog.name) //dog
dog.bark(); //汪汪汪
构造函数创建对象的方式要比字面量的方式要好用,但这种方式也有缺点,
用同一个原型对象创建的实例对象无法共享属性与方法,如:
var dog1 = new Animal('dog', '');
var dog2 = new Animal('dog', '');
console.log(dog1.specis) //dog
console.log(dog2.specis) //dog
dog1.specis = 'cat';
console.log(dog1.specis) //cat
console.log(dog2.species) //dog
可以看到对dog1的species属性的修改并没有反应到dog2对象上,这是因为每一个实例对象都会创建一个属性与对象的副本。这样当我们要创建多个实例对象的时候就会占用大量内存空间,而且对于那些可以共用的属性和方法来说,这完全是多余的,而且造成了极大的资源浪费。
三.prototype模式
在js中每一个函数都会有一个prototype属性指向一个对象,这个对象上的属性和方法都会被实例对象继承。因此我们可以将那些可以共用的属性放在prototype上。
function Animal(name, words) {
this.name = name;
this.words = words;
}
Animal.prototype.specis = 'dog';
Animal.prototype.bark = function() {
console.log(this.words);
};
var dog = Animal('dog', '汪汪汪');
console.log(dog.specis) //dog
dog.bark(); // 汪汪汪
所有实例上的species属性和bark方法其实是指向同一个内存地址的,因此只要我们改变prototype上的对应属性或方法,那么所有实例或方法上的属性和方法也就随之改变
Animal.prototype.specis = 'cat';
console.log(dog.specis) //cat
附加
当我们使用new操作符调用构造函数的时候,js内部过程如下:
- 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型
- 构造函数的属性和方法被加入到 this 引用的对象中
- 新创建的对象由 this 所引用,并且最后隐式的返回 this