简体   繁体   English

如何在JavaScript模块模式中的私有函数中调用公共函数

[英]How do I call a public function from within a private function in the JavaScript Module Pattern

How do I call a public function from within a private function in the JavaScript Module Pattern? 如何在JavaScript模块模式的私有函数中调用公共函数?

For example, in the following code, 例如,在以下代码中,

var myModule = (function() {
    var private1 = function(){
        // How to call public1() here?
        // this.public1() won't work
    }

    return {
        public1: function(){ /* do something */}
    }
})();

This question has been asked twice before , with a different accepted answer for each. 这个问题之前曾被问过两次 ,但每个问题的答案都不同。

  1. Save a reference to the return object before returning it, and then use that reference to access the public method. 在返回对象之前,请保存对它的引用,然后使用该引用访问public方法。 See answer . 答案
  2. Save a reference to the public method in the closure, and use that to access the public method. 在闭包中保存对public方法的引用,并使用该引用访问public方法。 See answer . 答案

While these solutions work, they are unsatisfactory from an OOP point of view. 虽然这些解决方案有效,但从OOP的角度来看,它们并不令人满意。 To illustrate what I mean, let's take a concrete implementation of a snowman with each of these solutions and compare them with a simple object literal. 为了说明我的意思,让我们对每种解决方案分别进行一个雪人的具体实现,并将其与简单的对象文字进行比较。

Snowman 1: Save reference to return object 雪人1:保存对返回对象的引用

var snowman1 = (function(){
  var _sayHello = function(){
    console.log("Hello, my name is " + public.name());
  };

  var public = {
    name: function(){ return "Olaf"},
    greet: function(){
      _sayHello();
    }
  };
  return public;
})()

Snowman 2: Save reference to public function 雪人2:保存对公共功能的引用

var snowman2 = (function(){
  var _sayHello = function(){
    console.log("Hello, my name is " + name());
  };
  var name = function(){ return "Olaf"};

  var public = {
    name: name,
    greet: function(){
      _sayHello();
    }
  };
  return public;
})()

Snowman 3: object literal 雪人3:物件文字

var snowman3 = {
    name: function(){ return "Olaf"},
    greet: function(){
      console.log("Hello, my name is " + this.name());
    }
}

We can see that the three are identical in functionality and have the exact same public methods. 我们可以看到这三个函数在功能上相同,并且具有完全相同的公共方法。

If we run a test of simple overriding, however 但是,如果我们测试简单覆盖

var snowman = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
                 // but snowman2 says "Hello, my name is Olaf"

we see that #2 fails. 我们看到#2失败了。

If we run a test of prototype overriding, 如果我们进行原型覆盖测试,

var snowman = {};
snowman.__proto__ = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
                 // but #1 and #2 both reply "Hello, my name is Olaf"

we see that both #1 and #2 fail. 我们看到#1和#2都失败了。

This is a really ugly situation. 这是一个非常丑陋的情况。 Just because I've chosen to refactor my code in one way or another, the user of the returned object has to look carefully at how I've implemented everything to figure out if he/she can override my object's methods and expect it to work! 仅仅因为我选择了以一种或另一种方式重构代码,返回对象的用户就必须仔细研究我如何实现一切以弄清楚他/她是否可以覆盖我的对象的方法并期望它能工作! While opinions differ here, my own opinion is that the correct override behavior is that of the simple object literal. 尽管此处的观点有所不同,但我个人的观点是正确的覆盖行为是简单对象文字的行为。

So, this is the real question: 因此,这才是真正的问题:

Is there a way to call a public method from a private one so that the resulting object acts like an object literal with respect to override behavior? 有没有一种方法可以从私有方法中调用公共方法,以使生成的对象在覆盖行为方面像对象文字一样工作?

You can use this to get the object your privileged method greet was called on. 你可以用this来让你的特权方法的对象greet被称为上。

Then, you can pass that value to your private method _sayHello , eg using call , apply , or as an argument: 然后,您可以将该值传递给您的私有方法_sayHello ,例如,使用callapply或作为参数:

var snowman4 = (function() {
    var _sayHello = function() {
        console.log("Hello, my name is " + this.name);
    };
    return {
        name: "Olaf",
        greet: function() {
            _sayHello.call(this);
        }
    };
})();

Now you can do 现在你可以做

var snowman = Object.create(snowman4);
snowman.greet(); // "Hello, my name is Olaf"
snowman.name = "Frosty";
snowman.greet(); // "Hello, my name is Frosty"

And also 并且

snowman4.greet(); // "Hello, my name is Olaf"
snowman4.name = "Frosty";
snowman4.greet(); // "Hello, my name is Frosty"

With module pattern, you hide all the innates of an object in local variables/functions, and usually employ those in your public functions. 使用模块模式,您可以将对象的所有先天都隐藏在局部变量/函数中,并且通常在公共函数中使用它们。 Each time a new object is created with a module pattern, a new set of exposed functions - with their own scoped state - is created as well. 每次使用模块模式创建新对象时,也会创建一组新的公开函数-具有自己的作用域状态。

With prototype pattern, you have the same set of methods available for all objects of some type. 使用原型模式,您可以使用同一组方法来处理某种类型的所有对象。 What changes for these methods is this object - in other words, that's their state. 这些方法的变化是this对象-换句话说,就是它们的状态。 But this is never hidden. 但是, this是从来没有隐藏。

Needless to say, it's tough to mix those. 不用说,很难将它们混合在一起。 One possible way is extracting the methods used by privates into a prototype of the module's resulting object with Object.create . 一种可能的方法是使用Object.create使用的方法提取到模块生成的对象的原型中。 For example: 例如:

var guardian = function() {
    var proto = {
        greet: function () {
            console.log('I am ' + this.name());
        },
        name: function() {
            return 'Groot';
        }
    };
    var public = Object.create(proto);
    public.argue = function() {
        privateGreeting();
    };

    var privateGreeting = public.greet.bind(public);
    return public;
};

var guardian1 = guardian();
guardian1.argue(); // I am Groot
var guardian2 = guardian();
guardian2.name = function() {
  return 'Rocket';
};
guardian2.argue(); // I am Rocket
var guardian3 = guardian();
guardian3.__proto__.name = function() {
  return 'Star-Lord';
};
guardian3.argue(); // I am Star-Lord

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在使用javascript模块模式时,如何从私有方法中调用公共方法? - How can i call a public method from within a private one when using the javascript Module Pattern? 如何从javascript模块模式中的函数原型访问私有属性? - How do I access private properties from function prototype in javascript module pattern? javascript模块模式:从私有函数向模块添加私有属性 - javascript module pattern: add private property to module from private function javascript:如何将参数传递给对象内的私有函数? - javascript: how do I handover an argument to a private function within an object? 在模块模式的构造函数中调用私有函数 - call private function in the constructor of module pattern 如何从JavaScript中的私有函数访问公共函数 - How to access public function from a private function in javascript 从JavaScript中的私有函数访问公共函数 - Access public function from private function in JavaScript 从公共方法调用模块的私有函数 - Calling a private function of a module from a public method 如何在javascript中调用函数对象中的子函数 - How do I call a sub-function from within a function object in javascript JavaScript,在不使用eval的情况下将私有函数作为公共方法内的字符串调用(Revealing pattern) - JavaScript, call private function as a string inside public method without using eval (Revealing pattern)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM