我不太喜欢动态编程语言,但我已经编写了相当多的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

这些幻灯片也帮了大忙。


当前回答

这个“.prototype”属性的确切用途是什么?

标准类的接口变得可扩展。例如,您正在使用Array类,还需要为所有数组对象添加自定义序列化程序。你会花时间编写一个子类,还是使用合成或。。。prototype属性通过让用户控制类可用的成员/方法的精确集合来解决这个问题。

将原型视为一个额外的vtable指针。当原始类中缺少一些成员时,将在运行时查找原型。

其他回答

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

这个“.prototype”属性的确切用途是什么?

标准类的接口变得可扩展。例如,您正在使用Array类,还需要为所有数组对象添加自定义序列化程序。你会花时间编写一个子类,还是使用合成或。。。prototype属性通过让用户控制类可用的成员/方法的精确集合来解决这个问题。

将原型视为一个额外的vtable指针。当原始类中缺少一些成员时,将在运行时查找原型。

原型允许您创建类。如果不使用原型,那么它将成为静态的。

这里有一个简短的例子。

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

在上面的例子中,您有静态函数调用测试。该函数只能由obj.test访问,您可以将obj想象为一个类。

其中如下代码所示

function obj()
{
}

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

obj已成为一个现在可以实例化的类。可以存在多个obj实例,它们都具有测试功能。

以上是我的理解。我正在把它做成一个社区维基,所以如果我错了,人们可以纠正我。

我发现在引用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

重要的是要理解对象的原型(可通过object.getPrototypeOf(obj)或通过不推荐的__proto__属性获得)和构造函数的原型属性之间存在区别。前者是每个实例上的属性,后者是构造函数上的属性。也就是说,Object.getPrototypeOf(newFoobar())引用与Foobar.prototype相同的对象。

参考:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes