我见过的几乎每个揭示模块模式教程都会显示一个公共方法访问私有方法不用使用“方法。调用(这,...) ”
这似乎可以完成工作,但是如果你在私有方法中做一个跟踪(这个),它将显示“Window”。这感觉就像潜在的陷阱。
我应该使用call
(或apply
),还是会引入不必要的复杂性?
plunk:data URI scheme
编辑:我的想法是,通过使用“调用”,它以某种方式使它“更安全”,因为上下文是api对象而不是全局命名空间。var Module = (function () {
var _privateVar = "PRIVATE!";
var api = {
publicMethod: publicMethod
}
return api;
function publicMethod() {
privateMethod();
privateMethod.call(this);
};
function privateMethod(message) {
console.log(_privateVar, this);
};
})();
Module.publicMethod();
答案 0 :(得分:0)
没有最佳做法。两个
function privateFunction(self, message) { // also popular: `that`
// do something with `self`
}
…
privateFunction(this, …);
和
function privateMethod(message) {
// do something with `this`
}
…
privateMethod.call(this, …);
很好。坚持一种风格并保持代码库的一致性。但是,第一个可能更受欢迎,因为许多私有函数实际上是静态的,并且不需要使用实例,因此它简化了为实例使用显式参数的事情(而不是假设/希望函数是使用预期的this
值调用。
答案 1 :(得分:0)
过去几天我一直在努力解决这个问题,很高兴能够遇到这个问题。但是,经过一些实验,至少有一个案例的答案似乎都不令人满意:在公共和私人职能部门之间传递数据。
以下是三个示例,使用' call',' bind'和一个普通的电话。绑定似乎是将私有方法保留在本地范围内的唯一方法,并且还允许私有方法和公共方法之间的数据交换。将上下文传递给私有方法的另一个建议仍然是让私有方法在模块外部执行(如果我理解正确的话)。
有趣的是,使用普通呼叫(有/无严格模式)允许数据交换,即使私有方法的上下文未定义' /'窗口'。 / p>
使用' bind':
"use strict";
var home = (function(){
var bob = function(){
console.log("Bob's scope: " + Object.keys(this)); // "Bob's scope: init"
var bob_says = "Hello";
var fBound = alice.bind(this);
var alice_reply = fBound(bob_says);
console.log("Alice answered: " + alice_reply); // "Alice answered: Hello Bob"
};
var alice = function(bob_greeting){
var scope = this ? Object.keys(this) : this;
console.log("Alice's scope: " + scope); // "Alice's scope: init"
console.log("Bob said: " + bob_greeting); // "Bob said: Hello"
return bob_greeting + " Bob";
};
return { init : bob };
})();
home.init();
使用'来电':
"use strict";
var home = (function(){
var bob = function(){
console.log("Bob's scope: " + Object.keys(this)); // "Bob's scope: init"
var bob_says = "Hello";
var alice_reply = alice.call(this, bob_says);
console.log("Alice answered: " + alice_reply); // "Alice answered: undefined Bob"
};
var alice = function(self, bob_greeting){
var scope = this ? Object.keys(this) : this;
console.log("Alice's scope: " + scope); // "Alice's scope: init"
console.log("Bob said: " + bob_greeting); // "Bob said: undefined"
return bob_greeting + " Bob";
};
return { init : bob };
})();
home.init();
没有电话或绑定:
"use strict";
var home = (function(){
var bob = function(){
console.log("Bob's scope: " + Object.keys(this)); // "Bob's scope: init"
var bob_says = "Hello";
var alice_reply = alice(bob_says);
console.log("Alice answered: " + alice_reply); // "Alice answered: Hello Bob"
};
var alice = function(bob_greeting){
var scope = this ? Object.keys(this) : this;
console.log("Alice's scope: " + scope); // "Alice's scope: undefined"
console.log("Bob said: " + bob_greeting); // "Bob said: Hello"
return bob_greeting + " Bob";
};
return { init : bob };
})();
home.init();
更新和可能的答案。 我好奇地想看看爱丽丝是否在没有打电话的情况下打电话给#39;或者'绑定',并且她的上下文是未定义的(或窗口),她是否可以访问家中的私人变量'?是的,所以我对OP(和我自己)的初步回答就是正常调用私人功能:没有'绑定',没有'呼叫'并且不需要传递上下文,而是使用严格的"如果你在运行私有函数时看到窗口上下文出现错误。似乎没有在'窗口中创建新属性,并且如果窗口具有与私有函数同名的对象(无论严格模式是打开还是关闭),则不会发生冲突。如果有问题,我还没有碰到过它们。
"use strict";
var alice = "Hi, I'm global's Alice";
var home = (function(){
var bob = function(){
console.log("Bob's scope: " + Object.keys(this)); // "Bob's scope: init"
var bob_says = "Hello";
var alice_reply = alice(bob_says);
console.log("Alice answered: " + alice_reply); // "Alice answered: Hello Bob. I'm in the garage."
};
var alice_location = "in the garage.";
var alice = function(bob_greeting){
var scope = this ? Object.keys(this) : this;
console.log("Alice's scope: " + scope); // "Alice's scope: undefined"
console.log("Bob said: " + bob_greeting); // "Bob said: Hello"
return bob_greeting + " Bob. I'm " + alice_location;
};
return { init : bob };
})();
home.init();
console.log(alice);
答案 2 :(得分:-1)
你的Module
永远不会在它自己的上下文中,因此调用它的静态函数将导致this
成为全局对象。
-
你可以尝试来修复它(通过创建一个“newable”对象):
const Module = (function () {
var _privateVar = "PRIVATE!";
const Api = function () {
};
function publicMethod() {
privateMethod();
privateMethod.call(this);
};
function privateMethod(message) {
console.log(_privateVar, this);
};
Api.protoype.publicMethod = publicMethod;
return Api;
});
const module = new Module();
console.log(module.publicMethod());