它不起作用,因为这就是 JavaScript 现在的工作方式。只是在构造函数中声明一个函数并不会在构造函数创建的对象上设置它,您必须显式地在对象和函数之间建立链接(直接通过将其分配给对象,或者更常见的是间接通过原型)。
你这样做的典型方式是通过原型继承,尽管你也可以直接将函数分配给单个对象(更多下文——但你谈到了“成员函数”,而在 JavaScript 中做类似事情的典型方式是通过原型) .
有几种方法可以设置原型继承。即使在旧版浏览器中也与广泛的 JavaScript 引擎兼容的经典方法是通过prototype
构造函数上的属性来引用对象。该对象成为通过创建的实例的原型new FunctionName
。您向该对象添加属性以在该函数创建的实例之间共享它们。
因此,使用原型继承:
function Init(name) {
this.name = name;
}
Init.prototype.displayName = function() {
alert(this.name);
};
var i = new Init("Mozilla");
i.displayName();
以上注意事项:
在 JavaScript 中,压倒性的约定是构造函数以大写字母开头。所以我叫它Init
而不是init
.
所有函数都自动具有一个prototype
属性,即一个空白对象。
我向该对象添加了一个属性,该属性displayName
引用了一个函数。
我没有对名称进行硬编码,而是将其Init
作为参数传递。
请注意,我将名称存储在新构造的实例的属性上;在对 的调用中Init
,该实例可作为this
.
类似地,因为displayName
作为从对象检索函数引用的表达式的一部分被调用,this
是对 的调用中的对象displayName
,因此this.name
具有名称。
为了简单起见,我将匿名函数分配给displayName
. (属性有名称,函数没有。)我倾向于不在实际代码中这样做。
通过原型构造的所有实例new Init
都将共享函数的相同副本。displayName
更多探索(在我的博客上):
如果您对在 JavaScript(和层次结构)中构建对象类感兴趣,您可能也对我的Lineage
工具包感兴趣。
从 ES5 开始,还有另一种选择:Object.create
. 这允许您直接创建对象并为其分配原型,而无需使用构造函数。但是正如您使用的那样new
,这意味着您正在使用构造函数,我不会对此进行详细介绍。
现在,如果您不想使用,则不必使用 JavaScript 的原型特性。例如,您可以这样做:
function Init(name) {
var name = name;
this.displayName = function() {
alert(name);
};
}
var i = new Init("Mozilla");
i.displayName();
这不使用 JavaScript 的原型特性,而是在displayName
每次调用时创建一个新函数Init
并将其直接分配给对象。(任何质量合理的 JavaScript 引擎都足够聪明,可以重用函数的代码,但每个实例都会有不同的函数对象)。以上也使name
属性完全私有,因为我们在每次调用时创建的函数是局部变量的闭包name
。(更多:闭包并不复杂)