6

我尝试了两种在 JS 中声明成员函数的方法:

function init() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
}
a = new init();
a.displayName()

function init() {
    var name = "Mozilla";
    displayName = function() {
        alert(name);
    }
}
a = new init();
a.displayName()

第一种方法告诉我的displayName()undefined。我看到它的方式是创建一个Function带有名称的类型变量displayName,因此它应该可以工作。有人愿意解释为什么它不起作用吗?

4

5 回答 5

13

它不起作用,因为这就是 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();

以上注意事项:

  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();

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

于 2012-12-04T10:05:14.240 回答
6

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

function init() {
    this.name = 'Mozilla';
}
init.prototype.displayName = function() {
    alert(this.name);
}

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

于 2012-12-04T10:04:21.127 回答
3

以下应该有效:

function Init() {
    var name = "Mozilla";
    this.displayName = function() {
        alert(name);
    }
}
a = new Init();
a.displayName()
于 2012-12-04T10:04:14.907 回答
2

您可以使用的标准之一是

var init = (function() {

    var name = "Mozilla"; // Shared by all instances

    function init() {
        this.name = "IE"; // Spesific to the created instance                  
    }    

    init.prototype = {
        displayName: function() {
            alert(name);
            alert(this.name);
        }        
    }

    return init;

})();

var a = new init();
a.displayName();​
于 2012-12-04T10:13:24.550 回答
0

在您的第一种方法中:

函数 init() { var name = "Mozilla"; 功能显示名称(){警报(名称);} } a = 新的初始化();a.displayName()

function displayName(){} 只能在 init() 中调用,类似私有函数,不能作为对象的公共函数(init())

于 2012-12-04T10:10:41.190 回答