Javascript面向对象

面向对象的概念

JavaScript 并不是面向对象的程序设计语言,面向对象设计的基本特征:继承、多态等没有得到很好的实现。在纯粹的面向对象语言里,最基本的程序单位是类,类与类之间提供严格的继承关系。比如 Java 中的类,所有的类都可以通过 extends 显式继承父类,或者默认继承系统的 Object 类。而 JavaScript 并没有提供规范的语法让开发者定义类。
JavaScript 中的每个函数都可用于创建对象,返回的对象既是该类的实例,也是Object 实例 看如下代码

<script type=" text/javascript"> 
	//定义简单函数
	function Person (name) 
	{ 
		this.name= name; 
	} 
	//使用 new 关键字 简单创建 Person 类的实例
	var p = new Person ('yeeku') ; 
	//如果p 是 Person 类的实例 则输出静态文本
	if (p instanceof Person) 
		document.writeln (" p是Person 的实例<br>"); 
	//如果p 是Object 类的实例,则输出静态文本
	if(p instanceof Object) 
		documen.writeln ("p是Object 的实例<br>") ; 
</script>

上面的 JavaScript 在定义 Person 函数的同时 ,也得到了 Person 类,因此程序通过 Person的对象既是 Person 实例 ,也是Object 类的实例

继承和 prototype

当定义函数时,函数中以 修饰的变量是实例属性,如果某个属性值是函数时,即可认为该属性变成了方法 例如如下代码

<script ype="text/javascript>
//创建 Person 函数
function Person(name , age) 
{ 
	this.name= name; 
	this.age = age; 
	//为 Prson 对象指定 info 方法
	this.info= function()
	{ 
		//输出 Person 实例的 name、age 属性
		docurnent.writeln("姓名:" + this.name);
		docurnent.writeln("年龄:" + this.age);
	}
	//创建 Person 实例 pl
	var pl = new Person ('yeeku', 29) ; 
	//执行 pl的info 方法
	pl.info() ; 
	documen.writeln ("<hr />") ; 
	//创建 Person 实例 p2
	var p2 = new Person ('wawa' , 20) ; 
	//执行 p2的info 方法
	p2.info() ;
</script>

代码中在定义 Person 函数的同时,也定义了一个Person 类,而且该Person 函数就是该Person 类的构造器,该构造器不仅为 Person 实例完成了屈性的初始化,还为 Person 实例提供info 方法。
但使用上面方法为 Person 类定义增加 info 方法相当不好,主要有如下两个原因。

  • 性能低下: 因为每次创建 Person 实例时,程序依次向下执行,每次执行程序中粗体字代码时都将创建一个新的info 函数—— 当创建多个Person 对象时,系统就会有很多个info 函数——这就会造成系统内存泄涌,从而引起性能下降 。实际上 info 函数只需一个就够了
  • 使得 info 函数中的局部变量产生闭包: 闭包会扩大局部变握的作用域,使得局部变量 一直存活到函数之外的地方。看如下 代码
<script type=" text/javascript " > 
	//创建 Person 函数
	function Person() 
	{ 
		// locVal 是个局部变量 原本应该该函数结束后立即失效
		var locVal = 'XXXXXX';
		this.info= function() 
		{
			//此处会形成闭包
			document.writeln("locVal 的值为:" + locVal);
			return locVal; 
		}
	} 
	var p = new Person(); 
	//调用p对象的info 方法
	var val = p.info () ; 
	//输出 val 返回值 该返回值就是局部变量 locVal
	alert(val);
</script>

由于在 info 函数里访问了局部变量 locVal 所以形成了闭包,而导致 locVal 变量的作用域被扩大,,即使离开 info程序依然可以访问到局部变量的值。
JavaScript 所有类(也就是函数)都有 prototype 属性 如果为 JavaScript类的prototype属性增 加属性、 方法,则可视为对原有类的扩展 我们可理解为 增加了 prototype 性的类继承了原有类——这就是 JavaScript 所提供的一种伪继承机制 看如下程序

<script type="text/javascript">
	function Person(name,age)
	    {
	        this.name = name;
	        this.age = age;
	        // this.info= function()
	        // { 
	        //     document.writeln("姓名 :" + this.name + "<br>" ) ; 
	        //     document.writeln ("姓名 :" + this.age + "<br>" ) ; 
	        // }
	    }
	    Person.prototype.walk = function()
	    {
	        document.writeln(this.name + 'kkk <br>');
	    }
	    //document.writeln('<br>');
	    var p1 = new Person ('yeeku',29);
	    // p1.info();
	    var p2 = new Person ('leegang',30);
	    // p2.info(); 
	    //document.writeln ('<br>');
	    p2.walk(); 
	    p1.walk();
</script>

在为 Person 类增加 walk 方法之前 p1 对象不能调用walk方法,当为Person 类增加了walk 实例方法之后 p2 对象以及前面 p1对象都拥有 walk 方法 ,所以可调用walk 方法
上面程序采用 prototype为Person类增加了 walk 方法 这样会让所有 Person共享 walk 方法,而且该walk 方法不在 Person 函数之内 不会产生闭包。
这可被当成一种“伪继承“;但这种“伪继承"的实质是修改了原有的类 并不是产生了一 新的子类,这一点尤其需要注意 因此原有的那个没有 walk 方法的 Person 类将不再存在!

使用 apply call 实现伪继承

上面介绍的伪继承的关键在千子类构造器需要以 this 作为调用者来调用父类构造器 ,这样父类构造器中的 this 就会变成代表子类,子类就可以得到原父类定义的实例属性和方法 ,因此这种伪继承方式完全可以用 apply和call 来实现,只要在使apply 或call 调用时指定 this作为调用者即可。

<script type="text/javascript">
    function Animal(sex,age)
    {
        this.sex = sex;
        this.age = age;
    }
    Animal.prototype.say = function()
    {
        console.log(this.age + "nian!");
    }
    //定义狗类
    function Dog(sex,age,bark){
        Animal.apply(this,[sex,age]);
        this.bark = bark;
    }
    Dog.prototype = new Animal();
    Dog.prototype.intro = function(bark)
    {
        console.log("这是个%s 狗,%s叫", this.sex , this.bark);   
    }
    var hsq = new Dog("母",2,"wang...");
    hsq.intro();
    hsq.say();
</script>

以下两语句作用完全相同

Person.call(this,name,age);
Person.apply(this,[name,age]);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值