2010-05-21 79 views
4

我最近才刚刚开始编程,并且完全自学成才,不幸的是我没有详细的计算机科学课程的好处。最近我一直在阅读关于JavaScript的许多内容,并且我试图从JavaScript的原型本质中找到类中的好处。这个问题似乎是在一个更好的中间被拉下来的,我想看看它的经典方面。古典结构与原型结构相比有什么好处?

当我看到原型例如:

var inst_a = { 
    "X": 123, 
    "Y": 321, 
    add: function() { 
    return this.X+this.Y; 
    } 
}; 
document.write(inst_a.add()); 

再经典的版本

function A(x,y){ 
    this.X = x; 
    this.Y = y; 
    this.add = function(){ 
    return this.X+this.Y; 
    }; 
}; 
var inst_a = new A(123,321); 
document.write(inst_a.add()); 

我开始考虑这一点,因为我期待在新的ECMAScript第5版和大量的人似乎有些担心他们没有添加一个班级系统。

+2

好问题;我在这里问了一个类似的问题:http://stackoverflow.com/questions/2800964/what-are-the-benefits-of-prototypal-inheritance-over-classical – Pierreten 2010-05-21 15:31:57

+0

我会通读一下,开始。我没有在我的搜索中找到它。谢谢! – Rixius 2010-05-21 15:32:54

回答

3

如果不使用psuedoclassical样式,继承是不可能的。看看道格拉斯克罗克福德对它有什么say。即使你使用的是纯粹的原型对象结构,你也必须为继承创建一个构造函数(这是Crockford所做的,然后将其抽象为create方法,然后将其称为纯原型)

+0

感谢您的链接。 – Rixius 2010-05-21 16:03:44

+0

+1为继承 - 优秀的一点和我最喜欢的OOP部分之一。 – Josh 2010-05-21 16:10:04

2

使用第二种方法,您可以创建A的实例,允许您一次有多个实例。例如:

var inst_one = new A(123,321); 
var inst_two = new A(456,654); 

// some meaningful code here... 
document.write(inst_one.add()); 


// some more meaningful code here... 
document.write(inst_two.add()); 

您提供的例子是微不足道的,因此,让一个更直观的例子:

function Comment(user,text){ 
    this.user = user; 
    this.text = text; 
    this.toString = function(){ 
    return '<span class="comment">'+this.text+' - <a class="user">'+this.user+'</a></span>'; 
    }; 
}; 


var comments = someFunctionThatReturnsALotOfCommentObjects(); 
for(c=0;c<comments.length;c++) 
    document.getElementById('comments_container').innerHTML += comments[c].toString(); 

这(希望)演示了能够创建一个类的多个实例的好处。这不是一个基本的JavaScript概念,它是一个基本的概念,如果你没有正式的编程课程,这可能是你为什么不熟悉它的原因。

+0

您还可以使用inst_a的原型创建另一个inst_ *并更新X和Y或添加更多属性。我个人会实现一个Object.clone,负责复制。 – Rixius 2010-05-21 15:39:09

+0

@Rixius哦,是的。我可以花一整天时间创建OOP如何有用的示例:-D – Josh 2010-05-21 15:40:31

+0

感谢您提供更好的示例。 – Rixius 2010-05-21 15:43:28

3

当您通过new创建对象时,它将使用它的原型链来查找实例中未找到的属性。

因此,例如,您可以将add方法添加到A.prototype一次,而不是每次创建A的新实例时重新定义相同函数的新副本。

function A(x,y){ 
    this.X = x; 
    this.Y = y; 

}; 
//define add once, instead of every time we create a new 'A' 
A.prototype.add = function(){ 
    return this.X+this.Y; 
    }; 
+0

+1,这是更好的风格 – Josh 2010-05-21 15:39:31

0

古典版本允许你声明私有变量的范围在对象“内部”,而原型版本不允许。

+0

不正确。您可以在原型版本中创建闭包。 – Josh 2010-05-21 15:41:04

1

为了公平起见JavaScript 确实有课。那么,也许有人会争论,但我认为它只是头发的语义分裂。如果一个类被认为是用于创建对象的蓝图,那么JavaScript函数可以以这种身份提供服务。这里没有在功能上多区别就在这里,唯一的形式:

class someObj 
{ 
    private int x; 
    public int returnX() 
    { 
     return x; 
    } 
} 
someObj temp = new someObj(); 

-

function someObj { 
    var x; 
    this.returnX = function() { 
     return x; 
    }; 
} 
var temp = new someObj(); 

下,它们是不同的引擎盖,但你可以使用任何一种形式来服务同一端。

原型在继承上真的不同。在原型继承中,当你创建一个新对象时,你真的在​​复制原型对象的一个​​实例,然后向它添加新的字段或成员。另一方面,古典遗产并不是处理一个实例,而只是一个“蓝图”。例如,在JavaScript中你会说:

temp.prototype = new someOtherObj(); //Creating a new instance to serve as the prototype. 

在经典的语言,你可以说:

class someObj : someOtherObj //Copying the "blue print" over. 

言下之意是,数据将在原型语言派生的对象之间共享。我曾经编写过一个函数,并通过JavaScript中的原型创建了另一个函数。这个基础对象持有对DOM对象的引用,并且当我在一个子对象中更改它时,它将更改该子对象的所有实例。这是因为,原型语言再次来自实例,而不是“蓝图”。