JavaScript .prototype如何工作?

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

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

我记得很久以前与人们进行过多次讨论(我不确定自己在做什么),但是据我了解,这里没有一个课堂的概念。这只是一个对象,这些对象的实例是原始对象的副本,对吧?

但是,此“ .prototype”属性在JavaScript中的确切目的是什么?它与实例化对象有何关系?

更新:正确的方法

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

这些幻灯片也确实起到了很大作用。

Itachi伽罗2020/03/09 18:28:44

只是您已经有一个对象,Object.new但使用构造函数语法时仍然没有对象。

猪猪十三2020/03/09 18:28:44

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

参考:https : //developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Object_prototypes

米亚Stafan2020/03/09 18:28:44

另一个显示__proto__原型构造函数关系的方案: 在此处输入图片说明

小卤蛋卡卡西2020/03/09 18:28:44

原型创建新的对象通过克隆现有对象因此,实际上,当我们考虑原型时,可以真正地考虑克隆或复制某些内容而不是进行组合。

小哥Stafan2020/03/09 18:28:44

在理解这类内容时,我总是喜欢类比。在我看来,与原型低音继承相比,“原型继承”相当令人困惑,尽管原型是更简单的范例。实际上,对于原型而言,确实没有继承,因此名称本身就具有误导性,它更像是一种“委托”。

想象一下....

您正在读高中,正在上课,今天有一个测验,但是您没有笔来填写答案。h!

您正坐在可能有笔的朋友Finnius旁边。您问,他环顾四周办公桌没有成功,但他没有说“我没有笔”,而是一个好朋友,他与其他朋友Derp核对了他是否有笔。Derp确实有一支备用笔,并将其传递回Finnius,后者将其交给您以完成测验。Derp已将钢笔委托给Finnius,后者已将钢笔委托给您使用。

这里重要的是,Derp不会把笔给您,因为您与他没有直接关系

这是原型工作方式的简化示例,其中在数据树中搜索您要寻找的东西。

蛋蛋飞云2020/03/09 18:28:44

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

简单对象继承

Jim小小2020/03/09 18:28:44

让我告诉您我对原型的理解。我不会在这里将继承与其他语言进行比较。我希望人们不再比较语言,而只是理解语言本身。理解原型和原型继承非常简单,下面我将向您展示。

原型就像模型一样,您可以基于该模型创建产品。要理解的关键点是,当您使用另一个对象作为原型创建对象时,原型与产品之间的联系是永恒的。例如:

var model = {x:2};
var product = Object.create(model);
model.y = 5;
product.y
=>5

每个对象都包含一个称为[[prototype]]的内部属性,可以通过该Object.getPrototypeOf()函数进行访问Object.create(model)创建一个新对象并将其[[prototype]]属性设置为对象模型因此,当您这样做时Object.getPrototypeOf(product),将获得对象模型

产品中的属性按以下方式处理:

  • 当访问属性以仅读取其值时,将在范围链中查找该属性。对变量的搜索从产品开始直至其原型。如果在搜索中找到这样的变量,则搜索将在此处停止,并返回值。如果在范围链中找不到此类变量,则返回undefined。
  • 写入(更改)属性后,该属性总是写在产品对象上。如果产品尚不具有此类属性,则将隐式创建和编写该产品。

使用原型属性进行的对象链接称为原型继承。那里很简单,同意吗?

小小阿飞2020/03/09 18:28:43

我发现obj_n.prop_X在引用“原型链”作为递归约定时会很有帮助

如果obj_n.prop_X不存在,检查obj_n+1.prop_X哪里obj_n+1 = obj_n.[[prototype]]

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

obj_1.prop_X = obj_1.[[prototype]].[[prototype]]..(k-times)..[[prototype]].prop_X

您可以在此处按其属性找到Javascript对象之间的关系图:

js对象图

http://jsobjects.org

村村AL2020/03/09 18:28:43

当构造函数创建对象时,该对象隐式引用构造函数的“ prototype”属性,以解决属性引用的问题。构造表达式的“ prototype”属性可以由程序表达式的builder.prototype引用,添加到对象原型的属性可以通过继承由共享原型的所有对象共享。

伽罗神奇2020/03/09 18:28:43

《面向对象的JavaScript权威指南》 -简短而清晰的约30分钟的视频解释所提出的问题(原型继承主题从5:45开始,尽管我更喜欢听整个视频)。该视频的作者还创建了JavaScript对象可视化器网站http://www.objectplayground.com/在此处输入图片说明 在此处输入图片说明

TonyEvaL2020/03/09 18:28:43

“ .prototype”属性的确切目的是什么?

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

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

2020/03/09 18:28:43

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

原型链

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

向原型添加功能/变量的优点是,它只能在内存中一次,而不是每个实例一次。

这对于继承也很有用,因为原型链可以包含许多其他对象。

小小JinJin蛋蛋2020/03/09 18:28:43

阅读此主题后,我对JavaScript原型链感到困惑,然后我发现了这些图表

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance * [[protytype]] *和功能对象的<code> prototype </ code>属性

这是一个清晰的图表,以按原型链显示JavaScript继承

http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/

这个包含一个示例代码和一些漂亮的图表。

原型链最终归结为Object.prototype。

通过将子类的原型设置为与父类的对象相等,每次都可以在技术上根据需要扩展原型链。

希望对理解JavaScript原型链也有帮助。