8

编辑:对于那些以后看到这篇文章的人来说,这个网站对于我消化 Javascript 无疑是至关重要的。如果您来自传统的 OOP 背景,我强烈推荐它。UML-esq 图很棒。

我仍然无法理解 Javascript 中的 .prototype 属性是什么。它只是对另一个对象的引用吗?或者它是对指向另一个对象的指针的引用?我来自 C/C++/x86,只是看不到它是如何工作的。让我们看一些我目前如何看待事物的例子;指出我的错误以了解事情的运作方式会有所帮助。我什至不知道其中一些是否是有效的语法。ObjectFunction分别是全局对象/函数对象。

1                                        // Global.prototype = ??
2                                        // Function.prototype = ??
3 
4   var obj1 = {};                       // obj1.prototype = Object 
5   obj2 = {};                           // obj2.prototype = Object
6
7   var func1 = function() {};           // func1.prototype = Function
8   func2 = function() {};               // func2.prototype = Function
9   function func3() {}                  // func3.prototype = Function  
10

我很混乱。

11  var Foo = function() { this.prop1 = 0; }
12  var foo = new Foo();                 // should it be 'new Foo' or 'new Foo()'?
13  // Foo.prototype = Function
14  // foo.prototype = Foo
15  var Goo = function() { this.prop2 = 0; }
16  var goo = new Goo();
17  // goo.prototype = Goo
18  goo.prototype = new Foo();
19  // goo.prop1 now exists ?

我也不明白交换原型。

20  function A () {
21     this.prop1 = 1;
22  }
23  function B () {
24     this.prop2 = 2;
25  }
26  function C () {
27     this.prop3 = 3;
28  }
29  C.prototype = new B();
30  var c = new C();
31  // c.prop1 = 1
32  // c.prop2 = 2
33  // c.prop3 = undefined
34  C.prototype = new A();
35  // c.prop2 = 2???
36  // c.prop3 = 3

我无法理解这个概念。我不太明白。我不明白克隆对象如何获得自己的本地数据副本,但是对原始对象(原型)的更改以某种方式级联到克隆。我一直在摆弄 FigureBug 尝试一些东西,但在精神上我无法想出一个与我看到的每个示例一致的想法

C++ 可能是一个巨大的怪物,但至少我确切地知道发生了什么。在这里......我正在使用我最好的猜测......我想只是一个新的范例。无论如何,谢谢你能帮忙......我在这个.prototype上颠倒了。

4

2 回答 2

4

哇,这是很多问题。让我们来解决它们。

它只是对另一个对象的引用吗?或者它是对指向另一个对象的指针的引用?

JavaScript 中没有指针。然而,持有“对象”的变量或属性实际上持有对该对象的引用,因此其他变量可以持有对同一对象的引用。

Global.prototype = ??

定义了所有全局变量的全局对象(window如果需要)没有原型(不要关心某些环境中的异常)。

我仍然无法理解 Javascript 中的 .prototype 属性是什么。

.prototype属性是所有函数对象都有的属性,指向它们的原型对象(一个普通对象)。

您不能将它与每个对象具有的内部原型引用混淆。该原型指向在其中查找对象本身没有的属性的对象。

Function.prototype = ??

这是所有 Function 对象继承的对象。它包含类似callor的东西bind

var obj1 = {};              // obj1.prototype = Object
var func1 = function() {};  // func1.prototype = Function

是的,有点。我认为您已经掌握了概念,但不知道术语。虽然func.prototype是另一回事,但该obj.prototype属性甚至不存在。但是,您的意思是内部原型- 我们可以通过Object.getPrototypeOf函数访问它们。而且它们不是指构造函数,而是它们的原型对象。这是更正:

Object.getPrototypeOf(obj1) === Object.prototype
Object.getPrototypeOf(func1) === Function.prototype

它应该是'new Foo'还是'new Foo()'?

没关系,它们是等价的。当您想要传递参数时,您只需要显式地使用括号。

var Foo = function() { this.prop1 = 0; }
var foo = new Foo();

同样,您的假设是正确的,但表达错误。让我们来看看细节。

上面,我谈到了“原型对象”。那些是什么?它们是由每个函数隐式创建的普通对象。在这种情况下,它是Foo.prototype- 一个空对象。所以我们在这里处理三个对象:Foo构造函数、它的Foo.prototype原型对象和foo实例。

有什么特别之处foo?这是new操作员要做的第一件事。当一个函数作为构造函数被调用时 - 使用new- 然后.prototype访问它的属性并实例化一个新对象,并将其内部原型设置为该原型对象。这就是神奇的事情。之后在新实例上调用该函数,这this就是新对象;在您的情况下,它会在实例上创建.prop1属性。然后返回结果(并分配给foo)。

现在如何使用那个魔法?重点是在原型对象上创建属性,然后将被继承。

// modify `Foo.prototype`, the object which `foo` inherits from:
Foo.prototype.prop2 = 1;
console.log(foo.prop2); // 1!

我也不明白交换原型。

问题是这是完全不可能的。一旦实例化,一个对象的原型链是相当静态的。但是,您不需要经常这样做。

goo.prototype = new Foo();

那没有用,因为该.prototype属性不是您所期望的。

var c = new C();
C.prototype = new A();

这确实只工作一点点。看看上面做了什么new- 它只查找.prototype构造函数的属性一次。然后内部原型保持锁定 - 您无需更改c实例。但是,如果您现在要创建一个新实例var d = new C(),那么它将从该A实例继承。

我希望这有帮助; 如果您还有其他问题,请发表评论。

于 2013-07-15T20:35:14.227 回答
2

当对象本身没有定义它时,原型用于在读取期间搜索属性。写入总是发生在对象本身上

你打电话时

// An instance of Foo ({prop1:0}) is set as the 
// prototype (to all instances of Goo)
var goo = new Goo();

// 0, from the prototype
console.log(goo.prop1); 

// Read from the object itself (set in Goo's constructor)
console.log(goo.prop2); 

// New instance, same prototype as goo
var goo2 = new Goo();
console.log(goo2.prop1) ; // 0, still from the prototype

// Setting is always at the object level, not the prototype
goo.prop1 = 5;

// goo2 is still reading from the prototype
console.log(goo2.prop1); 

注意

不要为了设置继承而实例化父类。看看为什么在这里http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

于 2013-07-15T17:36:22.393 回答