设为首页 加入收藏

TOP

JavaScript面向对象设计(一)
2017-02-08 08:16:44 】 浏览:391
Tags:JavaScript 面向 对象 设计

java script中Java语言不一样,它没有类这个说法,更没有子类父类一说,所以它所谓的继承机制,也是和其他语言完全不同的。


创建对象三种方式


1.最简单的方式,创建一个object对象,然后为它添加属性和方法


var person=new object();
person.name="zhangsan";
person.age=20;
person.sayName=function(){alert(this.name);};


2.工厂方式


本质上就是对上述最简单的方式的包装。


function createPerson(name,age)
{
var person=new object();
person.name=name;
person.age=age;
person.sayName=function(){alert(this.name);};
return person;
}


缺点是不知道对象的类型。


3 构造函数模式


即定义一个函数,该函数作为类似类中的构造函数,用于生成对象


function Person(name,age)
{
this.name=name;
this.age=age;
this.sayName=function(){alert(this.name);};
}


通过new方式创建对象,var person1=new Person("zhangsan",20);


该方式经历4个步骤


1,创建一个新对象


2,函数的作用域付给力新对象,this就表示了新的对象


3,执行函数中的代码,为新对象设置属性


4,返回新对象。


构造函数也是普通函数,任何函数只要用new操作符调用,都可以成为构造函数。


Person作为普通函数调用的话,this就是window对象。


Person("zhangsan",20);


window.sayName();


缺点是太浪费资源,每个实例中的属性都是不同的,特别是方法不能复用:


var person1=new Person("zhangsan",20);


var person2=new Person("zhangsan",20);


person1.sayName==person2.sayName// false


4,原型模式


每个函数都有一个prototype属性,定义在其中的属性,被各个实例对象所共享。也就是说,实例对象的属性和方法,分成两种,一种是自己定义的,另一种是prototype中共享的。 以Person为例子,按原型模式申明类:


function Person(){}
Person.prototype.name="zhangsan";
Person.prototype.age=20;
Person.prototype.sayName=function(){alert(this.name);};
var person1=new Person();
var person2=new Person();


此时person1这的属性和person2中的属性是指向同一个引用。


person1.sayName==person2.sayName// true


理解原型


constructor属性,函数的prototype属性有一个constructor属性,该属性的值默认情况下指向该prototype属性所在的函数。比如:


Person.prototype.constructor



function Person(){}


看一个图,更明白点



其中__proto__是内部属性,java script脚本中是没有的,只能通过chrome调试的时候才能看到。所有实例对象的__proto__都指向其构造器的prototype。


person1和person2对象的__proto__内部属性都指向了Person的原型,和Person自身没有任何关系。


当person1的sayName方法调用的时候,实际会执行2次查找,现在person1实例上找sayName,找不到,会去person1指向的原型上去找。


上述可知道,如果在person1上也找到sayName方法,那么原型上的方法就无法被调用到了。


通过方法 hasOwnProperty可以判断一个方法是在实例中还是在原型中。


再次强调,实例中的指针仅指向原型,而不是指向构造函数。


通过快捷写法


function Person(){}


Person.prototype.name="zhangsan";


Person.prototype.age=20;


Person.prototype.sayName=function(){alert(this.name);};


这种写法比较罗嗦


可以用json方式来写:


function Person(){}


Person.prototype={


name:"zhangsan",


age:20,


sayName:function(){alert(this.name);}


}


这种写法比较简洁,但是有一个问题,就是constructor属性的只不再指向Person了,这种语法等于完全重写了默认的prototype,因此constructor属性也被指到Object构造函数了。如果有必要的话,需要把constructor值手动赋值:


function Person(){}
Person.prototype={
name:"zhangsan",
age:20,
sayName:function(){alert(this.name);}
}


原型模式缺点,就是由于其共享性。它的所有属性是共享的,对于函数来说,求之不得,对于字段属性,这种共享可能会引起大问题。因此,单独使用原型模式很少见。


取长补短


同时使用构造函数模式和原型模式,非常简单,把需要共享的放到原型中,不需要共享的放到构造函数中。


function Person(name,age)
{
this.name=name;
this.age=age;
}
Person.prototype={
sayName:function(){alert(this.name);}
}


这种方式是目前最流行的方式。


还有动态原型模式,寄生构造函数模式,稳妥构造函数某事,不作介绍。


继承(主要两种方法,原型链和call/apply)


原型链,利用原型让一个引用类型继承另一个引用类型的属性和方法。


如果原型对象指向了另一个类型的实例,那么原型对象指向实例-->指向另一个原型对象-->constructor指向所在的函数。


这个就是所谓的原型链。如下图中SuperType和SubType展现的那样,SubType继承了SuperType。



上图中可以看到,原理存在于SuperType的实例中的所有属性和方法,都能在SubType中访问到了。


用代码表示如下:


function SuperType() {
this.property =true;
}
SuperType.prototype.getSuperValue =function() {
? ? returnthis.property;
}
function SubType() {
? ? this.subproperty =false;
}
//发生继承行为
SubType.prototype =new SuperType();
SubType.prototype.getSubValue =function() {
? ? returnthis.subproperty;
}
var instance =

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇GC.Collect如何影响垃圾回收 下一篇Java Garbage Collection基础之Ja..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目