我不太喜欢动态编程语言,但我已经编写了相当多的JavaScript代码。我从未真正了解过这种基于原型的编程,有人知道它是如何工作的吗?

var obj = new Object();
obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

我记得前一段时间我和人们进行了很多讨论(我不太确定我在做什么),但据我所知,没有什么课的概念。它只是一个对象,这些对象的实例是原始对象的克隆,对吗?

但JavaScript中这个“.prototype”属性的确切用途是什么?它与实例化对象有什么关系?

更新:正确方式

var obj = new Object(); // not a functional object
obj.prototype.test = function() { alert('Hello?'); }; // this is wrong!

function MyObject() {} // a first class functional object
MyObject.prototype.test = function() { alert('OK'); } // OK

这些幻灯片也帮了大忙。


当前回答

另一种尝试是用更好的图片解释基于JavaScript原型的继承

其他回答

另一种尝试是用更好的图片解释基于JavaScript原型的继承

原型通过克隆现有对象来创建新对象。所以,当我们考虑原型时,我们真的可以考虑克隆或复制一些东西,而不是虚构。

我发现在引用obj_n.prop_X时,将“原型链”解释为递归约定很有帮助:

如果obj_n.prop_X不存在,请检查obj_n+1.prop_X,其中obj_n+1=obj_n。[[原型]]

如果prop_X最终在第k个原型对象中找到,则

obj_1.prop_X=obj_1.[[原型]].[[原型]]..(k次)..[[原型]].prop_X

您可以在此处通过Javascript对象的财产找到它们之间的关系图:

http://jsobjects.org

Javascript没有通常意义上的继承,但它有原型链。

原型链

如果在对象中找不到对象的成员,它会在原型链中查找它。链由其他对象组成。可以使用__proto__变量访问给定实例的原型。每个对象都有一个,因为javascript中的类和实例之间没有区别。

向原型中添加函数/变量的优点在于,它只需在内存中存在一次,而不是针对每个实例。

它对于继承也很有用,因为原型链可以由许多其他对象组成。

在Java、C#或C++等实现经典继承的语言中,首先要创建一个类——一个对象的蓝图——然后可以从该类创建新对象,或者可以扩展该类,定义一个新类来扩充原始类。

在JavaScript中,您首先创建一个对象(没有类的概念),然后您可以扩充自己的对象或从中创建新对象。这并不难,但对于习惯了传统方式的人来说,有点陌生,很难消化。

例子:

//在JavaScript中定义一个函数对象以容纳人员var Person=函数(名称){this.name=名称;};//向已定义的对象动态添加一个新的getterPerson.prototype.getName=函数(){返回this.name;};//创建Person类型的新对象var john=新人(“john”);//试试吸气剂警报(john.getName());//如果现在我修改人,John也会得到更新Person.prototype.sayMyName=函数(){alert('你好,我的名字是'+this.getName());};//对john调用新方法john.sayMyName();

到目前为止,我一直在扩展基本对象,现在我创建了另一个对象,然后从Person继承。

//Create a new object of type Customer by defining its constructor. It's not 
//related to Person for now.
var Customer = function(name) {
    this.name = name;
};

//Now I link the objects and to do so, we link the prototype of Customer to 
//a new instance of Person. The prototype is the base that will be used to 
//construct all new instances and also, will modify dynamically all already 
//constructed objects because in JavaScript objects retain a pointer to the 
//prototype
Customer.prototype = new Person();     

//Now I can call the methods of Person on the Customer, let's try, first 
//I need to create a Customer.
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();

//If I add new methods to Person, they will be added to Customer, but if I
//add new methods to Customer they won't be added to Person. Example:
Customer.prototype.setAmountDue = function(amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
    return this.amountDue;
};

//Let's try:       
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

var Person=函数(名称){this.name=名称;};Person.prototype.getName=函数(){返回this.name;};var john=新人(“john”);警报(john.getName());Person.prototype.sayMyName=函数(){alert('你好,我的名字是'+this.getName());};john.sayMyName();var客户=函数(名称){this.name=名称;};Customer.prototype=新角色();var myCustomer=新客户(“梦想股份有限公司”);myCustomer.sayMyName();Customer.prototype.setAmountDue=函数(amountDue){this.amountDue=amountDue;};Customer.prototype.getAmountDue=函数(){return this.amountDue;};myCustomer.setAmountDue(2000);警报(myCustomer.getAmountDue());

虽然如上所述,我不能调用setAmountDue(),但对Person调用getAmountDu()。

//The following statement generates an error.
john.setAmountDue(1000);