在JS中声明成员函数

Yot*_*tam 5 javascript function member

我已经尝试了两种方法在JS中声明一个成员函数:

function init() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
}
a = new init();
a.displayName()
Run Code Online (Sandbox Code Playgroud)

function init() {
    var name = "Mozilla";
    displayName = function() {
        alert(name);
    }
}
a = new init();
a.displayName()
Run Code Online (Sandbox Code Playgroud)

第一种方法告诉我的displayName()undefined.我创建了一个Function带有nae 的类型变量的方式displayName,因此它应该可以工作.任何人都在乎解释为什么它不起作用?

谢谢

T.J*_*der 10

它不起作用,因为现在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();
Run Code Online (Sandbox Code Playgroud)

以上注释:

  1. 在JavaScript中,压倒性的约定是构造函数以大写字母开头.所以我打电话给Init而不是init.

  2. 所有函数都自动prototype在它们上面有一个属性,这是一个空白对象.

  3. 我向该对象添加了一个属性,该属性displayName引用了一个函数.

  4. 我将其Init作为一个参数传递而不是对名称进行硬编码.

  5. 请注意,我将名称存储在新构造的实例上的属性上; 在调用中Init,该实例可用作this.

  6. 类似地,由于displayName被称为检索来自物体的函数参照表达式的一部分,this是调用内的对象displayName,因此this.name具有名称.

  7. 为了简单起见,我分配了一个匿名函数displayName.(该属性有一个名称,函数没有.)我倾向于不在实际代码中这样做.

  8. 通过原型构建的所有实例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();
Run Code Online (Sandbox Code Playgroud)

这不使用JavaScript的原型功能,而是displayName每次调用Init时直接创建一个新函数并将其直接分配给对象.(任何合理质量的JavaScript引擎都足够聪明,可以重用函数的代码,但每个实例都会有不同的函数对象).上面也使name属性完全私有,因为我们在每次调用时创建的函数是对局部变量的闭包name.(更多:闭包并不复杂)


Thi*_*ter 6

要创建类似于成员函数的东西,您需要将其添加到构造函数的原型:

function init() {
    this.name = 'Mozilla';
}
init.prototype.displayName = function() {
    alert(this.name);
}
Run Code Online (Sandbox Code Playgroud)

我还强烈建议您阅读有关JavaScript中的对象系统如何工作的内容.在MDN上有一篇非常好的文章:https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript