6

好的,我应该知道这个问题的答案,但由于某种原因,我从来没有真正理解或需要真正了解 JavaScript。

我的问题是:查看下面的代码示例,我的理解是正确的还是我遗漏了一些信息。


样品 1

需要实例化函数(或类)才能使用该IsOld方法,并且IsOld将为每个实例创建一个单独的函数副本。

function MyClass1() {
    this.IsOld = function (age) {
        if (age > 40) {
            return true;
        }
        return false;
    };
}

// sample usage
var m1 = new MyClass1();
console.log(m1.IsOld(34));

样品 2

需要实例化但与MyClass1脚本引擎不同的是不需要IsOld为每个类实例创建方法的副本。

var MyClass2 = (function () {
    function MyClass2() { }

    MyClass2.prototype.IsOld = function (age) {
        if (age > 40) {
            return true;
        }
        return false;
    };

    return MyClass2;
})();

// sample usage
var m2 = new MyClass2();
console.log(m2.IsOld(34));

样品 3

无需实例化函数/类即可访问该IsOld方法。该方法的单个实例IsOld用于所有调用。

var MyClass3 = {
    IsOld: function (age) {
        if (age > 40) {
            return true;
        }
        return false;
    },
};

// sample uage
console.log(MyClass3.IsOld(34));

注意:我猜这里有很多类似的问题/答案,但由于某种原因,我找不到对我来说真正有意义的问题/答案。

4

3 回答 3

2

你的理解似乎是正确的。

如果“需要实例化”是指使用“新”关键字,我想在这里添加一些内容。

在 JavaScript 中使用 new 关键字并不是创建新实例的唯一方法。(根据评论编辑)任何函数都可以作为构造函数。

当你使用'new'关键字后跟任何函数(比如'x')时,它的作用是

  1. 创建新对象(比如“y”),并将函数 x 的原型设置为新对象(y)的原型。
  2. 在新创建的对象 y 的上下文中调用函数“x”,即 this 将在函数“x”中引用这个新对象“y”
  3. 如果函数没有返回对象,则返回由 new 运算符创建的新对象 'x' 作为 new 表达式的结果。

这是 Douglas Crockford ( http://javascript.crockford.com/ )为您学习 JavaScript 的一个很好的资源

因此,如果您关心内存(应该如此),请使用构造函数,并将所有常用方法添加到函数原型中,就像您在示例 2 中所做的那样。

然后所有这些方法将被继承到使用此函数作为构造函数创建的所有对象。但是,如前所述,我认为示例 2 可以更简单:

var MyClass2 = function MyClass2() { };

MyClass2.prototype.IsOld = function (age) {
    if (age > 40) {
        return true;
    }
    return false;
};

var obj = new MyClass2();
于 2012-11-19T10:14:40.460 回答
1

在我看来,对于类的结构和 Javascript 的动态特性存在一些误解:对于所有呈现的案例,“类”的每个实例都会创建一个新的未命名函数。

如果您想以更传统的方式(如 C++ 或 Java)声明“类”,您最好:

1)定义功能:

function MyClass_IsOld(age) {
    return (age > 40);
} 

2)创建“类”并定义其原型:

function MyClass() { /* put any instance constructor logic here */ };
MyClass.prototype.IsOld = MyClass_IsOld;

3)使用类:

var myInstance = new MyClass();
console.log(myInstance.IsOld(37));

如果您想将“方法”用作常规函数,请在全局范围内声明它,例如:

function MyClass_IsOld(age) {
    return (age > 40);
} 
function MyClass() { /* put any instance constructor logic here */ };
MyClass.prototype.IsOld = MyClass_IsOld;

var myInstance = new MyClass();
console.log(myInstance.IsOld(37));        // use as a method
console.log(MyClass_IsOld(37));           // use as a function

如果要隐藏实现细节,请创建一个闭包:

var MyClass = (function () {
    function _MyClass_IsOld(age) {
        return (age > 40);
    } 
    function _MyClass() { /* put any instance constructor logic here */ };
    _MyClass.prototype.IsOld = _MyClass_IsOld;  // use as a method

    return _MyClass;
})();

var myInstance = new MyClass();
console.log(myInstance.IsOld(37));        // use as a method
console.log(MyClass_IsOld(37));           // ERROR: undefined function
于 2012-11-19T10:50:28.060 回答
1

据我所知,您在所有 3 种情况下都是正确的。

  1. 确实需要实例化IsOld,并且对于每个实例都会创建新函数。
  2. 不需要IsOld像在原型中那样实例化。
  3. 不需要实例化IsOld,因为 MyClass3 已经是一个实例(对象不是函数)。
于 2012-11-19T10:00:56.620 回答