注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

isblog主页

或许不一定要做得最多,但一定要做得最好! 能力就是一种财富,积累越多,就越体现你

 
 
 

日志

 
 

javascript定义类或对象四种写法  

2014-03-27 10:04:32|  分类: javascript |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

JavaScript实现经典的类,总结有四种方法:

  ● 构造函数方式;

  ● 原型方式;

  ● 构造函数+原型的混合方式

       ● 动态原型方式


构造函数方式

  构造函数用来初始化实例对象的属性和值。任何JavaScript函数都可以用作构造函数,构造函数必须使用new运算符作为前缀来创建新的实例。

var Person = function (name) {
    this.name = name;
    this.sayName = function(){
        alert(this.name);
    };
}
  
//实例化
var tyler = new Person("tylerzhu");
var saylor = new Person("saylorzhu");
tyler.sayName();
saylor.sayName();
//检查实例
alert(tyler instanceof Person);

构造函数方式跟传统的面向对象语言是不是很相识!只不过是class关键字用function替换了。

  注意:不要省略new否则Person(“tylerzhu”) //==>undefined。当使用new关键字来调用构造函数时,执行上下文(context)从全局对象(window)变成一个空的上下 文,这个上下文代表了新生成的实例。因此,this关键子指向当前创建的实例。所以省略new时,没有进行上下文切换会在全局对象中查找name,没有找 到而创建一个全局变量name返回undefined。

原型方式

        构造函数方式简单,但是存在一个浪费内存的问题。如上面的例子中实例化了两个对象tyler、saylor,表面上好像没什么问题,但是实际上对于每一个实例对象,sayName()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容申请内容。

  alert(tyler. sayName == saylor. sayName) 输出false!!!

  Javascript中每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例共享。

var Person = function (name) {
    Person.prototype = name;
    Person.prototype.sayName = function(){
        alert(this.name);
    }
}
  
//实例化
var tyler = new Person("tylerzhu");
var saylor = new Person("saylorzhu");
tyler.sayName();
saylor.sayName();
  
//检查实例
alert(tyler instanceof Person);

这时tyler、saylor实例的sayName方法,都是同一个内存地址(指向prototype对象),因此原型方法更节省内存。

  但是看tyler.sayName();saylor.sayName();两者输出,会看出问题 —— 它们都输出“saylorzhu”。因为原型所有属性都共享,只要一个实例改变其他的都会跟着改变,所以实例化对象saylor覆盖了tyler。

构造函数+原型的混合方式

  构造函数方式可以为同一个类的每一个对象分配不同的内存,这很适合写类的时候设置属性;但是设置方法的时候我们就需要让同一个类的不同对象共享同一个 内存了,写方法用原型的方式最好。所以写类的时候需要把构造方法和原型两种方式混合着用(很多类库提供的创建类的方法或框架的写类方式本质上都是:构造函 数+原型)。

var Person = function (name) {
    this.name = name;
    
}
Person.prototype.sayName = function(){
    alert(this.name);
}  
//实例化
var tyler = new Person("tylerzhu");
var saylor = new Person("saylorzhu");
tyler.sayName();
saylor.sayName();
//检查实例
alert(tyler instanceof Person);

这样即可通过构造函数构造不同name的人,对象实例也都共享sayName方法,不会造成内存浪费。

动态原型方式

  使用效果和构造函数+原型方式一样,只是写法略有不同

var Person = function (name) {
    this.name = name;
//原型方法写在这里,用if进行判断
if(typeof Person._initialized == "undefined")
{
     Person.prototype.sayName = function(){
         alert(this.name);
}
Person._initialized = true;
    }
}
  
//实例化
var tyler = new Person("tylerzhu");
var saylor = new Person("saylorzhu");
tyler.sayName();
saylor.sayName();
  
//检查实例
alert(tyler instanceof Person);

        new 对象时直到检查typeof Person._initialized 是否等于"undefined" 之前,这个构造函数都未发生变化.这行代码是动态原型方法中最重要的部分.如果这个值未定义,构造函数将用原型方式继续定义对象的方法,然后把Person._initialized设置为true. 如果这个值定义了(它的值为true时, typeof的值为Boolean), 那么就不再创建该方法.简而言之,该方法使用标志来判断是否己给原型赋予了任何方法.该方法只创建并赋值一次,传统的OOP开发者会高兴地发现,这段代码看起来更像其他语言中的类定义了.

总结:

推荐使用后面两种写法,可以提高脚本性能。后两种区别在于:

构造函数+原型的混合方式:混合的构造函数和原型方式,相当于把非函数属性和一般属性分开来写,这样new 新对象的时候,不会重复构造新函数,此时引用的知识函数对象的原型方法和函数对象的属性。但是,代码看起来没有封装起来而且,不影响任何东西。 

动态原型方式:完全利用JAVA的编程代码风格来实现JS的编程。这样的好处是让整个函数看起来像是把属性和方法都“封装”在一个函数体内,看起来更像一个“类”。(温故知新:JS中其实没有类,你要说有类,就可以把它看做一个function类),缺点是在于利用if()语句看起来不是很友好而已。


参考来自:

http://www.admin10000.com/document/1374.html

http://purpen.iteye.com/blog/104206

  评论这张
 
阅读(315)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018