Javascript 面向对象编程的理解
/*生成对象的原始模式
假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性。*/
var Cat = {
name : '',
color : ''
}
/*现在,我们需要根据这个原型对象的规格(schema),生成两个实例对象。*/
var cat1 = {}; // 创建一个空对象
cat1.name = "大毛"; // 按照原型对象的属性赋值
cat1.color = "黄色";
var cat2 = {};
cat2.name = "二毛";
cat2.color = "黑色";
/*原始模式的改进
我们可以写一个函数,解决代码重复的问题。*/
function Cat(name,color){
return {
name:name,
color:color
};
};
var cat3 = Cat("大毛","黄色");
var cat4 = Cat("二毛","黑色");
/*构造函数模式
为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。*/
function Cat1(name,color){
this.name=name;
this.color=color;
};
var cat11 = new Cat1("大毛","黄色");
var cat12 = new Cat1("二毛","黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色
/*这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。*/
alert(cat11.constructor == Cat1); //true
alert(cat12.constructor == Cat1); //true
alert(cat11.constructor.toString());
/*结果如下:
function Cat1(name,color){
this.name=name;
this.color=color;
};*/
alert(cat1.toString());//[object Object]
alert(cat1.constructor.toString());//function Object(){[native code]};
Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系。
alert(cat11 instanceof Cat1); //true
alert(cat12 instanceof Cat1); //true
var cat2 = function(name,color){
this.name=name;
this.color=color;
};
//alert(cat2.toString());//function(name,color){this.name=name;this.color=color;};
//alert(cat2.constructor.toString());//function Function(){[native code]};
function Cat2(name,color){
this.name = name;
this.color = color;
this.type = "猫科动物";
this.eat = function(){alert("吃老鼠");};
};
var cat21 = new Cat2("大毛","黄色");
var cat22 = new Cat2 ("二毛","黑色");
alert(cat21.type); // 猫科动物
cat21.eat(); // 吃老鼠
/*表面上好像没什么问题,但是实际上这样做,有一个很大的弊端。那就是对于每一个实例对象,
type属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。*/
alert(cat21.eat == cat22.eat); //false
/*Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。*/
function Cat3(name,color){
this.name = name;
this.color = color;
}
Cat3.prototype.type = "猫科动物";
Cat3.prototype.eat = function(){alert("吃老鼠")};
var cat31 = new Cat3("大毛","黄色");
var cat32 = new Cat3("二毛","黑色");
alert(cat31.type); // 猫科动物
cat31.eat(); // 吃老鼠
alert(cat31.eat == cat32.eat); //true
/*这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。*/
/*isPrototypeOf()
这个方法用来判断,某个proptotype对象和某个实例之间的关系。object1.isPrototypeOf(object2); 是用来判断指定对象object1是否存在于另一个对象object2的原型链中,是则返回true,否则返回false*/
alert(Cat3.prototype.isPrototypeOf(cat31)); //true
alert(Cat3.prototype.isPrototypeOf(cat32)); //true
/*hasOwnProperty()
每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。*/
alert(cat31.hasOwnProperty("name")); // true
alert(cat31.hasOwnProperty("type")); // false
/*3 in运算符
in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。*/
alert("name" in cat31); // true
alert("type" in cat31); // true
/*in运算符还可以用来遍历某个对象的所有属性。*/
for(var prop in cat31) { alert("cat31["+prop+"]="+cat31[prop]); };
/*此文转载,非自己编写*/
发表评论