欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaScript面向对象编程

程序员文章站 2022-05-09 14:24:26
...

JavaScript面向对象编程

面向对象编程主要涵盖:封装、继承、多态

1.封装

将属性和方法组合在一起形成一个类,通过new实例一个对象。这就是封装
先看一下js的一阶封装

 

<script>
var Cat = {
  name : '',
  color : ''
};
var cat1 = {}; // 创建一个空对象
cat1.name = "大毛"; // 按照原型对象的属性赋值
cat1.color = "黄色";
var cat2 = {};
cat2.name = "二毛";
cat2.color = "黑色";
</script>

 上面cat1和cat2都是参考Cat的属性设置的,但是两者之间似乎没有任何关系。
再来看看二阶封装——构造函数

 

<script>
function Cat(name,color){
	this.name = name;
	this.color = color;
}
var cat1 = new Cat("小明","黑色");
var cat2 = new Cat("小红","红色");
alert("cat1.constructor == Cat如果返回true,表示cat1的构造函数时Cat,也表示Cat就是构造函数:"+cat1.constructor == Cat);
alert(cat2.constructor == cat1.constructor);
alert(cat2.constructor);
alert(cat1.constructor);
</script>

 上下文:this
this永远指向当前代码的上下文

 

 

<script>
var name = "The Window";
var object = {
  name : "My Object",
  getNameFunc : function(){
		var than = this;
    return function(){
      return than.name;
    };
  }

};
alert(object.getNameFunc()());
</script>

 大家自己在火狐上面运行看看得到的结果。如果把上面的var than=this;去掉结果又是什么呢。好好体会this关键字。

 

Prototype形式的封装
我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象的用途是将该对象的实例共享所有属性和方法。那么,prototype就可以通过调用构造函数来创建那些对象实例的原型对象。
翻译白话:写一个对象函数,然后可以通过对象函数的prototype来定义其他的属性和方法,并且这个属性和方法都会被该对象的实例直接共享。
使用原型的好处是可以让对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中添加定义对象信息,而是可以直接将这些信息添加到原型中。使用构造函数的主要问题就是每个方法都要在每个实例中创建一遍。
直接使用构造函数来创建方法

 

<script>
function Cat(name,color){
	this.name = name;
	this.color = color;
	this.eat = function(){
		alert("吃鱼");
	}
}
var cat1 = new Cat("小明","黑色");
var cat2 = new Cat("小红","红色");
cat1.eat();
alert(cat1.eat == cat2.eat)
</script>

 用prototype来添加方法

 

 

<script>
function Cat(name,color){
	this.name = name;
	this.color = color;
	this.eat2 = function(){
		alert(1);
	}
	//return this;
}
//我们在2.html中已经说过,Cat就是指构造函数。而js里面有个特殊的的对象prototype对象。每一个函数都有prototype属性,这个属性指向prototype对象
Cat.prototype.eat=function(){
	
	alert(this.name+"吃鱼");
}
Cat.prototype.aa = "aa";
var cat1 = new Cat("小明","黑色");
var cat2 = new Cat("小明","黑色");

//alert(cat1);
alert(cat1.aa);
Cat.prototype.aa = "bb";
alert(cat1.aa);
alert(cat2.aa);
/**
var cat2 = new Cat("小红","红色");
//alert(Cat.eat()); //TypeError: Cat.eat is not a function
cat1.eat();
cat1.eat2();
alert(cat1.eat == cat2.eat);
alert(cat1.eat == cat2.eat);
*/
</script>

 
JavaScript面向对象编程
            
    
    博客分类: JavaScript JavaScript面向对象封装继承 
 好好体会一下上面的图。

 

①。因为所有函数都会有一个prototype属性,这个属性指向一个prototype对象(原型对象)。所以上面Cat对象的prototype属性指向原型对象。然后我们在原型对象上添加了一个eat方法。

②。所有通过Cat new出来的实体都会有一个匿名属性__proto__这个属性指向Cat指向的prototype对象。这个cat1和cat2就都具有eat方法。

③。原型对象具有一个constructor属性,这个属性指向自己的构造函数,那么上面的原型对象就会指向Cat方法

构造函数,实例,原型对象的区别
实例就是通过构造函数创建的。实例创造出来就具有constructor属性(指向构造函数)和__proto__属性(指向原型对象)。
构造函数中有一个prototype属性,这个属性是一个指针,指向它的原型对象。
原型对象内部也有一个指针(constructor属性)指向构造函数:Cat.prototype.constructor = Cat;
实例可以访问原型对象上定义的属性和方法。

继承

JavaScript实现继承的方式有很多,我们介绍几种简单并且使用的比较多的方式

继承是什么?
答:子类能够调用父类的方法和属性
上面的例子中,猫是动物。那么可以创建一个动物类。猫继承动物。前面描述了prototype的含义,那么是不是可以将猫的构造函数的prototype赋值为动物的对象。

继承方式一:

 

<script>
function Animal(typeName){
	this.typeName = typeName;
}
Animal.prototype.eat = function(){
	alert("吃");
};
function Cat(name,color){
	this.name = name;
	this.color = color;
	/**
	this.eat = function(){
		alert("吃鱼");
	}
	*/
}

Cat.prototype.eat = function(){
	alert("吃鱼");
}

Cat.prototype = new Animal("aa");
Cat.prototype.constructor = Cat;
var cat1 = new Cat("小明","黑色");
cat1.eat();
alert("Cat.prototype.constructor:"+Cat.prototype.constructor)
alert(cat1.typeName);
alert(cat1.name)
</script>


JavaScript面向对象编程
            
    
    博客分类: JavaScript JavaScript面向对象封装继承 
  

在上面可以看出一个问题,Cat.prototype.constructor指向的是Animal这就有点奇怪了,Cat明明是猫为什么会是动物呢,所以我们要重新将Cat的构造函数指向Cat。即:Cat.prototype.constructor=Cat
继承方式二:

 

 

<script>
function Animal(){
	this.typeName = "动物";
}
Animal.prototype.eat = function(){
	alert("吃");
};
Animal.prototype.attr = "属性"
function Cat(name,color){
	this.name = name;
	this.color = color;
	this.eat = function(){
		alert("吃鱼");
	}
}
Cat.prototype = Animal.prototype;
var cat1 = new Cat("小明","黑色");
cat1.eat();
alert(cat1.typeName);
alert(cat1.attr);
var animal = new Animal();
alert("查看cat1的构造函数是谁(cat1.constructor):"+cat1.constructor);
alert("查看Cat的构造函数是谁(Cat.prototype.constructor):"+Cat.prototype.constructor);
alert("查看cat1的构造函数是谁(animal.constructor):"+animal.constructor);
alert("查看Cat的构造函数是谁(Animal.prototype.constructor):"+Animal.prototype.constructor);
Cat.prototype.constructor =  Cat;
alert("查看cat1的构造函数是谁(cat1.constructor):"+cat1.constructor);
alert("查看Cat的构造函数是谁(Cat.prototype.constructor):"+Cat.prototype.constructor);
alert("查看cat1的构造函数是谁(animal.constructor):"+animal.constructor);
alert("查看Cat的构造函数是谁(Animal.prototype.constructor):"+Animal.prototype.constructor);
</script>

 查看例子:好处是可以不用创建Animal实例节约内存,坏处是Cat的原型对象和Animal的原型对象相同,对其中一个修改都会反映到另一个对象。而且Animal的构造函数不能有自己的属性和方法,不然Cat对象将继承不到这些属性
继承方式三:

 

<script>
function Animal(){
	this.typeName = "动物";
}
Animal.prototype.eat = function(){
	alert("吃");
};
Animal.prototype.attr = "属性"
function Cat(name,color){
	this.name = name;
	this.color = color;
	this.eat = function(){
		alert("吃鱼");
	}
}
//Cat.prototype = Animal.prototype;
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
var cat1 = new Cat("小明","黑色");
cat1.eat();
alert(cat1.typeName);
alert(cat1.attr);
var animal = new Animal();
alert("查看cat1的构造函数是谁(cat1.constructor):"+cat1.constructor);
alert("查看Cat的构造函数是谁(Cat.prototype.constructor):"+Cat.prototype.constructor);
alert("查看animal的构造函数是谁(animal.constructor):"+animal.constructor);
alert("查看Animal的构造函数是谁(Animal.prototype.constructor):"+Animal.prototype.constructor);
Cat.prototype.constructor =  Cat;
alert("查看cat1的构造函数是谁(cat1.constructor):"+cat1.constructor);
alert("查看Cat的构造函数是谁(Cat.prototype.constructor):"+Cat.prototype.constructor);
alert("查看animal的构造函数是谁(animal.constructor):"+animal.constructor);
alert("查看Animal的构造函数是谁(Animal.prototype.constructor):"+Animal.prototype.constructor);
</script>

 

  • JavaScript面向对象编程
            
    
    博客分类: JavaScript JavaScript面向对象封装继承 
  • 大小: 39.4 KB
  • JavaScript面向对象编程
            
    
    博客分类: JavaScript JavaScript面向对象封装继承 
  • 大小: 55 KB