论坛首页 Web前端技术论坛

基于对象的JavaScript编程 3

浏览 1298 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (7) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-25   最后修改:2009-11-25

基于对象的JavaScript编程(3

-JavaScript Object-Oriented Programming

                     By-Ryan Frishberg

Constructor

构造器

    所有的对象实例都有一个constructor属性,它返回建立当前对象的Function (既构造函数),例如:

function myConstructor(){  

}  

var str = new String("Some String");  

var obj = new Object();  

var myObj = new myConstructor();  

alert(str.constructor); // the native String() constructor  

alert(String) // the native String() constructor  

alert(obj.constructor); // the native Object() constructor  

alert(Object) // the native Object() constructor  

alert(myObj.constructor); // the user-defined myConstructor() constructor  

alert(myConstructor); // the user-defined myConstructor() constructor

 

    作者建议你去运行一下这段代码,我也强烈建议你去执行以下它。每一个alert都返回了一个方法体(构造器函数),就是这个方法创建了对应的对象。JavaScript的内建函数的构造器的内容返回的是"[native code]"

当你用typeof关键字去验证构造验证器属性的类型时,返回值会是和创建这个对象的方法一样,都是“function”。(这个不难理解,因为构造器本身就是一个function

 

 

alert(typeof str.constructor); // "function"  

alert(typeof String) // "function"  

alert(typeof obj.constructor); // "function"  

alert(typeof Object) // "function"  

alert(typeof myObj.constructor); // "function"  

alert(typeof myConstructor); // "function" 

    看到了吧这段alert全都弹出”function”,原因很简单因为对象的constructor属性是指向创建该对象的构造方法的,实际上它就是一个构造器方法。(有点和上面重复了)。

function myConstructor(){  

 var x = "y";  

 this.x = "x";  

 return x;  

}  

var myObj = new myConstructor();  

alert(myObj.constructor); // the myConstructor() function object  

alert(myObj.constructor()); // "y"

    这段比较有意思哈,呵呵。上面的方法调用的时候返回的是局部变量x,而不是对象的x属性的值。(详细说明一下:myObj.constructor指的是构造器函数,而myObj.constructor() 则调用了该构造器函数,运行一下上面代码就很清楚了)。这样每个对象都有一个构造器函数,同时在JavaScript中函数也是对象,那一个函数的类构造器又是什么呢?(有点绕,还是看代码清楚)

 

alert(myConstructor.constructor);  

alert(myObj.constructor.constructor);  

alert(myConstructor.constructor.constructor);  

alert(myObj.constructor.constructor.constructor);

    上面的代码全都返回内置函数Function()的构造器。

    尽管这个看起来不怎么重要,但是你不觉得很有意思吗?它正好证明了一个事实:构造器既是一种函数对象,同时也是"types of objects”.(作者要表达的意思应该就是构造器既是一个具体的对象也是指这一类对象 赋原文:Constructors are both "types of objects" as well as objects themselves (more specifically, Function objects).这样,Date既是指一个对象也是指这一类对象了,你可以创建一个Date的实例,也可以直接使用它。这点对于内置对象和用户自定义对象来说都是一样的。

    这种特性的实际意义在于,我们同门可以通过一个对象的构造器得出这个对象的类型。下面这些就懒得翻了:We can see whether it's a String object, created from the native String constructor function; whether it's an Object object, created from the native Object constructor function; or whether it's one of our user-defined objects, created from a user-defined constructor function.

 

   构造器函数(constructor())不仅仅是对象的一个方法,同时基本数据类型也有自己的构造器函数。那这个函数返回值是什么呢,实际上在创建一个基本数据类型的实例的时候并没有真正的构造函数运行:

var primitiveString1 = "This is a primitive string";  

var primitiveString2 = String("This is a primitive string");  

var stringObject = new String("This is a String object");  

primitiveString1.prop = "This is a property";   

primitiveString2.prop = "This is a property";  

stringObject.prop = "This is a property";  

alert(primitiveString1.prop) // "undefined"  

alert(primitiveString2.prop) // "undefined"  

alert(stringObject.prop) // "This is a property"  

alert(typeof primitiveString1); // "string"  

alert(typeof primitiveString2); // "string"  

alert(typeof stringObject) // "object"  

alert(primitiveString1.constructor); // "function String(){   

[native code] }"  

alert(primitiveString2.constructor); // "function String(){   

[native code] }"  

alert(stringObject.constructor); // "function String(){   

[native code] }"

 

    可以看到,基本数据类型的String和一个String对象都有相同的构造函数:内置的String()构造器。但是构造函数时基本数据类型拥有的唯一的属性/方法.这样这种类型就有了在内置构造器中定义的方法/属性。就是说基本数据类型只能包含已经定义好的属性和方法,用户不能随意给它添加新的属性。看一个例子,一个基本类型String包含且只包含在它的构造函数定义的属性/方法(当然这些属性/方法在String类的实例中也拥有)

       length

       anchor()

       big()

       bold()

       charAt()

       charCodeAt()

       concat()

       indexOf()

       lastIndexOf()

       sub()

       substr()

       substring()

 

但是一个String型的对象实例就可能拥有它自己独特的属性或方法了,例如:

var myStringObj = new String("This is a String object");  

myStringObj.prop = "This is a property of the object I created";  

alert(myStringObj.prop) // "This is a property of the object I created"

有时你可能需要将一个基本数据类型转换成对象类型。看下面的方法:

function myFunc(param){   

 param.property = "I want to add this property";  

 alert(param.property); // "undefined"  

   如果调用时传入一个基本数据类型的参数,那它就不能完成期望的目标了。而且实际上传入一个对象的话就会比较笨重。

 

 

myFunc(new String("This is a String object"));  

myFunc(new Number(5));

为了解决这个问题,Alex(谁啊?)指出可以这样:

function myFunc(param){  

 param = new param.constructor(param);  

 param.property = "I want to add this property";  

 alert(param.property); // returns "I want to add this property"  

    晕,又要开始晕乎了。先看一下前面的内容,当我们要将一个基本数据类型转换成对象类型时,我们可以这样做:

 

var myNum = 5;  

myNum = new Number(5);

继续:

var myNum = 5;  

myNum = new myNum.constructor(5);

   记得吧myNum.constructor()Number() 实际上是等价的,都调用构造器。这样就不难理解了,呵呵直接用myNum就可以:

 

var myNum = 5;  

myNum = new myNum.constructor(myNum);

    其他的基本数据类型也一样,这样我们就可以给一个方法传入基本数据类型,但是在方法内部我们就可以轻而一举的把它转换成对象,然后操作它的属性/方法什么的。

再来看看Prototype

    我们回过头来再来看看函数对象的prototype属性。继承在Java中是一个众所周知的特性。你会想到吗,在JavaScript中你也可以做到相同的事情。比如,有一个car对象,CorvetteAres是不同类型的轿车,但都是轿车。这样他们就可以从Car对象那里继承到一些基本的属性/方法。

 

    先创建以下要用到的这三个对象:Car,Corvette,Ares。然后再来探讨怎么实现后面两中车对Car的继承。

function Car(color){   

 this.wheels = 4;   

 this.doors = 4;   

 this.color = color;   

 this.speed = 0;   

 this.accelerate = function(){   

   this.speed+=20;   

 }   

 this.brake = function(){   

   this.speed-=20;   

 }   

}   

function Corvette(color){   

 // all of Car properties/methods   

 this.doors = 2;   

 this.color = color;   

 this.accelerate = function(){   

   this.speed+=40;   

 }   

}   

function Ares(color){   

 // all of Car properties/methods   

 this.doors = 2;   

 this.color = color;   

 this.accelerate = function(){   

   this.speed+=10;   

 }   

 this.brake = function(){   

   this.speed-=10;   

 }   

}   

var myCar = new Car("white");   

var myCorvette = new Corvette("black");   

var myAres = new Ares("red");

   Corvette是一款速度很快的跑车,我们设置它的加速度比普通车大一些。Dodge Ares是一辆老车,我们设置它的刹车有点失灵,加速度也小一些。现在我们就可以使用Corvette() Ares() prototype,然后给他们加上所有从Car类型继承过来的特性,然后再加上他们的个性信息。这个过程比较麻烦且不好理解,我们先再来验证一下prototype属性。

    Prototype属性是一个没有任何属性/方法的对象。我们给它添加属性/方法的时候,自动的就给这个对象的所有实例都添加了对应的内容。那么,如果我们不在对象的prototype对象上添加属性/方法,我们可以用别的包含我们想添加到当前对象的属性/方法的对象来替换掉当前对象的prototype对象(竟然搞出一句这么绕的句子,太有成就感了,嘎嘎,你们拍砖吧),闲言少叙,看例子:

 

 

Corvette.prototype.wheels = 4;   

Corvette.prototype.speed = 0;   

Corvette.prototype.brake = function(){   

 this.speed-=20;   

可以简单的用:

Corvette.prototype = new Car();

Ares也同样的设置:

 

Ares.prototype = new Car();

   现在两个子类型的车都包含了Car的属性/方法,当然可以在他们自己的构造函数中覆盖掉某些内容,例如 Corvette 型号车和 Ares 型号车都重写了door 属性为2.现在代码就成这样了:

function Car(color){   

 this.wheels = 4;   

 this.doors = 4;   

 this.color = color;   

 this.speed = 0;   

 this.accelerate = function(){   

   this.speed+=20;   

 }   

 this.brake = function(){   

   this.speed-=20;   

 }   

}   

function Corvette(color){   

 this.doors = 2;   

 this.color = color;   

 this.accelerate = function(){   

   this.speed+=40;   

 }   

}   

Corvette.prototype = new Car();   

function Ares(color){   

 this.doors = 2;   

 this.color = color;   

 this.accelerate = function(){   

   this.speed+=10;   

 }   

 this.brake = function(){   

   this.speed-=10;   

 }   

}   

Ares.prototype = new Car();   

var myCar = new Car("white");   

var myCorvette = new Corvette("black");   

var myAres = new Ares("red");

    现在我们就可以在CorvetteAres的对象中调用accelerate()和brake()这两个继承自父类的方法了。可以看到通过这种方法在JavaScript中不难实现继承。

Wrap-up(这段总结不翻了-。-)

Through this tutorial, I hope you've learned a general understanding of how JavaScript operates. In addition, I hope you've gained a basic knowledge of OOP and an understanding of the power of JavaScript as an object-based language. I suggest that you post any questions you might have in the SitePoint Forums; however, if you can't seem to find an answer to your JavaScript object question, I'd be more than happy to give it a shot if you email me at arielladog@yahoo.com  There have been many people who have helped me write this tutorial. In particular, though, I'd like to thank Alex Vincent, Jason Davis, and Jared for helping me to understand the finer points of JavaScript's object abilities.

 

 

论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics