2012-08-30 112 views
2

我想创建一个类常量,但我想我的新手级JavaScript理解显示。当这个代码执行:为什么需要通过实例访问原型?

var Class = function() {}; 
Class.prototype = { CONST : 1 }; 
var instance = new Class(), 
c1 = instance.CONST, 
c2 = Class.CONST; 

结果是c1 === 1c2 === undefined。为什么不是c2 === 1? JavaScript没有查找Class的原型链吗?

+0

我没有足够的信心把它放在一个答案中,但我会说,类没有原型链......它是一个构造函数。作为Class实例的对象具有您使用'Class.prototype = ...'创建的原型链。换句话说,'Class.prototype'没有引用'Class'对象的原型链,而是引用'Class'构造函数创建的对象的原型链。 – LarsH

+0

@LarsH - 我很确定函数对象有原型链。然而,你的评论的第二部分,很多都是澄清的。我正在将'Class'的'prototype'属性与原型链混合在一起。 –

+0

特德,我不否认函数对象有原型链......只是A.原型是对象A的原型链(我同意​​你的看法)。 – LarsH

回答

4

你试图做的是什么将被称为其他语言的类静态方法。
要做到这一点在Javascript中你必须写

Class.CONST = 1;那么你就可以Class.CONST;

调用它,如果你试图用实例方法来访问它像new Class().CONST,这将是不确定的

返回到您的问题,Class.prototype中的所有内容只能通过对象的实例(即通过new创建)访问,而不是Class本身。为什么?

考虑的new

Function.method('new', function() { 
    var that = Object.create(this.prototype); 
    var other = this.apply(that, arguments); 
    return (typeof other === 'object' && other) || that; 
}); 

第一Object.create(this.prototype)实施创建从this.prototype继承了一个全新的对象其中U通过Class.prototype = { Const : 1 }声明,那么它叫this.apply(that, arguments),它只是用that作为this打电话给你的声明类功能变量。然后它返回对象。你可以看到Class函数只是用来通过new将事物填充到新创建的对象中。只有创建的对象才能访问原型方法。

+1

好的。这就是让我困惑的原因。我处于(明显错误的)印象中,指派给'Class.prototype'的设置是为'Class'设置原型。所以如果我没有错的话,'prototype'键在设置构造函数时有特殊的意义,但它与构造函数本身的原型链无关;它只是用来为实例设置原型链。我现在有吗? (PS,难道你不能简单地设置'Class.CONST = 1' - 而不是一个函数返回1 - 获得一个“类常量”?) –

+0

是的,JavaScript只会查找原型链的一个通过Object.create()创建的对象,new仅仅是Java程序员的一个语法糖。 Class.CONST = 1很好,Class.Anything只是将Anything附加到Class对象 – yngccc

2

您正试图访问构造函数的CONST属性(Class = function(){})。在您实例化Class之前,CONST将不可用。

关于这对夫妻的良好的联系:

+1

最后一个链接非常有帮助。它清楚地表明构造函数的'prototype'属性与函数的原型链无关。 MDN文件中似乎缺少一些细节(我在发布问题之前已阅读过)。 –

0

Class是一个函数对象。函数对象没有CONST属性。它被用来构造一个'Class'对象。 'Class'对象是具有CONST属性的自定义对象,因为它是在构造函数中声明的。

1

简单的答案是,从实例其构造的公共原型继承,所以c1具有从Class.prototype(严格地说,这是该实例的私有财产[[Prototype]])继承了CONST属性。

在另一方面,ClassFunction一个实例,因此它从Function.prototype继承(即其私人[[Prototype]]Function.prototype),不Class.prototype,所以它不具有CONST属性。

对象的值[[Prototype]]在构建时设置并且永远不能更改。用其他对象替换Class.prototype只会影响新的实例。

请注意,在一些较旧的Mozilla浏览器(例如Firefox)中,有一个__proto__属性引用对象的[[Prototype]]并且可以设置,但现在已被弃用。

通常最好不要谈论有关javascript的类,因为它推断的行为和功能只能在一定程度上模拟。

相关问题