【问题标题】:JavaScript instance functions versus prototype functions [duplicate]JavaScript实例函数与原型函数[重复]
【发布时间】:2010-11-29 07:09:49
【问题描述】:

可能重复:
Use of 'prototype' vs. 'this' in Javascript?

我对各种JavaScript函数的理解如下:

function MyObj() {
    this.propOne = true;
    this.publicInstanceFunc = function() {
        if (propOne)
            return 'public instance function';
    }
    function privateFunc() {
        return 'private function only visible inside this constructor';
    }
}

MyObj.prototype.protoFunc = function() {
    if (this.propOne)
        return 'prototype function shared amongst all instances of MyObj';
}
  1. 这些正确吗?
  2. 在什么情况下应该将函数放在原型中(例如protoFunc)而不是在构造函数中(例如publicInstanceFunc)?
  3. 使用this 是访问原型函数内部属性的正确方法吗?

【问题讨论】:

    标签: javascript syntax prototype-programming


    【解决方案1】:

    您实际上可以通过将整个事物包装在一个自执行函数中来添加另一个级别的权限:

    var MyObj = (function() { // scoping
        var privateSharedVar = 'foo';
    
        function privateSharedFunction() {
            // has access to privateSharedVar
            // may also access publicSharedVar via explicit MyObj.prototype
            // can't be called via this
        }
    
        function MyObj() { // constructor
            var privateInstanceVar = 'bar';
            this.publicInstanceVar = 'baz';
    
            function privateInstanceFunction() {
                // has access to all vars
                // can't be called via this
            };
    
            this.publicInstanceMethod = function() {
                // has access to all vars
                // also known as a privileged method
            };
        }
    
        MyObj.prototype.publicSharedVar = 'quux';
    
        MyObj.prototype.publicSharedMethod = function() {
            // has access to shared and public vars
            // canonical way for method creation:
            // try to use this as much as possible
        };
    
        return MyObj;
    })();
    

    只有“公共”属性可以通过this 从外部访问。

    出于性能原因,您应该避免使用我所说的“实例”方法:对于其中的每一个,都必须为每个 MyObject 实例创建一个新的函数对象,而每个“共享”方法只有一个函数对象。

    【讨论】:

    • 很抱歉重新提出这个问题/答案,但是将外部函数包装在括号中是否有什么特别之处?例如(function(){ })(); 怎么样?不同于function(){}();
    • @Matt:外部括号强制将函数文字解释为表达式而不是语句;在这种情况下它们是不必要的,因为赋值已经强制这种解释,但是没有它,如果你省略括号,你应该得到一个语法错误
    • 感谢 Christoph 提供了这个出色的示例。如果您想在该命名空间中定义另一个对象,您会怎么做?例如,如果 MyObj 包含 MyObj2 的数组。您是否会将其定义为立即调用函数的一部分,使其位于 MyObj 的命名空间中?
    • 一个小问题:返回不应该是return new MyObj();吗?这就是我必须做的事情才能让它工作,但要让我没有破坏格式良好的代码。
    • @scader: 照原样,外部变量MyObj 将保存构造函数并且可以这样使用(即通过new MyObj() 实例化对象);如果您返回 new MyObj(),则外部 var 将仅保存该特定实例
    【解决方案2】:

    这些正确吗?

    错了。嗯,这取决于你想做什么。在 JavaScript 中实现类/实例样式继承没有一种公认的规范模型。

    但是这个:

        if (propOne)
    

    可能是一个错误,因为this.propOne 是所有者对象的属性,而propOne 本身是一个尚未声明的变量(这默认为全局变量,但通常是错误的) .

    在什么情况下应该将函数放在原型中(例如 protoFunc)与在构造函数中(例如 publicInstanceFunc)?

    原型上的函数集是所有对象共享的相同函数。它可以确定它属于哪个实例的唯一方法是在调用它时读取“this”。

    在构造函数中设置在“this”上的函数是MyObj 的每个实例的新函数。您可以使用 this 作为基于闭包而不是“this”绑定到所有者对象的替代方法,这样可以节省写出函数绑定的东西。这是一种不同的面向对象风格,通常不会与基于 this 的风格混合使用。

    【讨论】:

      【解决方案3】:

      1) 是的,您的代码是正确的。

      2) 当我想访问在构造函数本身范围内私有定义的其他成员时,我使用在构造函数中定义的函数,例如,当你想创建privileged methods 时。

      在构造函数上定义的公共函数,比在对象原型中添加简单函数的计算成本更高,但它们也为您提供了更多的灵活性。

      3) 是的,如果属性是公共的,您可以通过在原型扩展函数中使用 this 关键字来访问它,因为 this 指的是您的对象的实例。

      【讨论】:

        【解决方案4】:

        关于第二点,你扩展原型,让所有已经创建的对象都获得新方法。

        此外,允许您向内置对象添加方法(例如将trim() 添加到string)。

        【讨论】:

          猜你喜欢
          • 2016-10-04
          • 1970-01-01
          • 2021-02-12
          • 1970-01-01
          • 2015-03-06
          • 1970-01-01
          • 2018-06-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多