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

I-L*_*Kuo 8 javascript module-pattern

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

例如,在以下代码中,

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

    return {
        public1: function(){ /* do something */}
    }
})();
Run Code Online (Sandbox Code Playgroud)

此问题之前已被问过两次 ,每个问题都有不同的接受答案.

  1. 在返回之前保存对返回对象的引用,然后使用该引用访问公共方法.见答案.
  2. 在闭包中保存对public方法的引用,并使用它来访问public方法.见答案.

虽然这些解决方案有效,但从OOP的角度来看,它们并不令人满意.为了说明我的意思,让我们用这些解决方案中的每个解决方案对雪人进行具体实现,并将它们与简单的对象文字进行比较.

雪人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;
})()
Run Code Online (Sandbox Code Playgroud)

雪人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;
})()
Run Code Online (Sandbox Code Playgroud)

雪人3:对象文字

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

我们可以看到这三者在功能上是相同的,并且具有完全相同的公共方法.

但是,如果我们运行简单覆盖的测试

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"
Run Code Online (Sandbox Code Playgroud)

我们看到#2失败了.

如果我们进行原型覆盖测试,

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"
Run Code Online (Sandbox Code Playgroud)

我们看到#1和#2都失败了.

这是一个非常丑陋的情况.只是因为我选择重构我的代码在这种或那种方式,返回的对象的用户必须在我是如何实现的事情弄清楚,如果他/她可以覆盖我的对象的方法仔细看,并期望它的工作!虽然这里的意见不同,但我个人认为正确的覆盖行为是简单对象文字的行为.

所以,这是一个真正的问题:

有没有办法从私有方法中调用公共方法,以便生成的对象在覆盖行为方面就像对象文字一样?

Ori*_*iol 2

您可以使用它来获取调用this特权方法的对象。greet

然后,您可以将该值传递给您的私有方法_sayHello,例如使用call, apply, 或 作为参数:

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

现在你可以做

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

并且

snowman4.greet(); // "Hello, my name is Olaf"
snowman4.name = "Frosty";
snowman4.greet(); // "Hello, my name is Frosty"
Run Code Online (Sandbox Code Playgroud)