封装
Javascript是一种基于对象的语言,一切皆对象。但是,它又不是真正的面向对象,因为没有class(类)。
那么,如果要把属性(property)和方法(method)封装 成对象该如何呢?
1.生成对象的原始模式(对象字面量)
var Cat = {
name : '',
color : ''
};
var cat1 = {};
cat1.name = "小王";
car1.color = "黄色";
var cat2 = {};
cat2.name = "小熊";
cat2.color = "绿色";
这是最简单的封装。两个缺点:一是如果多生成几个实例,非常麻烦;二是实例于原型之间,没有任何办法可以看出有联系。
2.原始模式改进
写个函数,解决代码重复。
function Cat(name,color) {
return {
name : name,
color : color
}
}
生成实例,相当于在调用函数。
var cat1 = Cat("小王","黄色");
var cat2 = Cat("小熊","绿色");
问题:cat1和cat2之间没有任何内在的联系,不能反应出他们是同一个原型对象的实例。
3.构造函数模式
构造函数其实就是普通的函数但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this实例会绑定在 实例对象上。
function Cat(name,color) {
this.name = name;
this.color = color;
}
先在可以 生成实例对象了。
var cat1 = new Cat("小王","黄色");
var cat2 = new Cat("小熊","绿色");
cat1.name; // 小王
cat1.color; // 黄色
这是cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。
cat1.constructor == Cat; // true
cat2.constructor == Cat; // true
Javascript还提供了instanceof运算符,验证原型对象与实例之间的关系。
cat1 instanceof Cat; // true
cat2 instanceof Cat; // true
4.构造函数模式的问题
构造函数方法很好用,但存在一个浪费内存的问题。
假设为Cat原型添加一个不变的属性type,在添加一个方法eat,再生成实例,每个实例对象type属性和eat方法都是一模一样的,每次生成,都重复内容,缺乏效率。
function Cat(name,color) {
this.name = name;
this.color = color;
this.type = "动物";
this.eat = function () {alert("吃老鼠");}
}
同样方法,生成实例。
var cat1 = new Cat("小王","黄色");
var cat2 = new Cat ("小熊","绿色");
cat1.type; // 动物
cat1.eat(); // 吃老鼠
cat1.eat == cat2.eat; // false
5.prorotype模式
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
function Cat(naem,color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "动物";
Cat.prototype.eat = function () {alert("吃老鼠")};
生成实例。
var cat1 = new Cat("小王","黄色");
var cat2 = new Cat ("小熊","绿色");
cat1.type; // 动物
cat1.eat(); // 吃老鼠
所有实例的type属性和eat方法,其实都是同一个内存地址,指向prototype对象 ,因此提高了效率。
cat1.eat == cat2.eat; // true
6.prototype模式验证方法
- isPropertyOf()
用来判断某个prototype对象和某个实例之间的关系
Cat.property.isPropertyOf(cat1); // true
Cat.property.isPropertyOf(cat2); // true
```
- hasOwnProperty()
用来判断某个属性到底是本地属性还是继承自prototype对象的属性。
cat1.hasOwnProperty(“name”); // true
cat1.hasOwnProperty(“type”); // false
- in运算符
用来判断某个实例是否含有某个属性,不管是不是本地属性。
“name” in cat1; // true
“type” in cat1; // true
还可以用来遍历某个对象的所有属性
for(var p in cat1){
alert(“cat1[” + p + “]=” + cat1[p];)
}
“`
参考blog:
Javasctipt面向对象