Javascript JS私有方法未在每次构造函数调用时重新定义
如何使Javascript私有方法在每次调用构造函数时都不会重新定义 据我所知,在OOP-JS中,私有方法是在“类”的“构造函数方法”中定义的方法,每次实例化一个新的“对象”时调用。我在想也许函数声明(即Javascript JS私有方法未在每次构造函数调用时重新定义,javascript,oop,private,micro-optimization,Javascript,Oop,Private,Micro Optimization,如何使Javascript私有方法在每次调用构造函数时都不会重新定义 据我所知,在OOP-JS中,私有方法是在“类”的“构造函数方法”中定义的方法,每次实例化一个新的“对象”时调用。我在想也许函数声明(即function name(),而不是函数表达式var name=function())会起作用,但是我如何确保下面的代码只声明我的函数一次呢 function Tester() { function test () { console.log("executed");
function name()
,而不是函数表达式var name=function()
)会起作用,但是我如何确保下面的代码只声明我的函数一次呢
function Tester() {
function test () {
console.log("executed");
}
}
var t1 = new Tester();
var t2 = new Tester();
如何使Javascript私有方法在每次调用构造函数时都不会重新定义
你不能(好吧,看看下面有没有回旋的余地)。但是,除非您将拥有数千个Tester
实例,否则不要太担心它;大多数引擎可能会跨创建的多个函数对象重用底层代码。(注意,代码;不是函数对象或它关闭的上下文,它们必须是唯一的,并且每次都分配。但是它们不需要很大。当然,相当多的函数也相当小……)
…如何确保以下代码只声明我的函数一次
function Tester() {
function test () {
console.log("executed");
}
}
var t1 = new Tester();
var t2 = new Tester();
你可以肯定它不会;它在每次调用Tester
时声明函数。证人:
function Tester() {
this.test = test;
function test () {
console.log("executed");
}
}
var t1 = new Tester();
var t2 = new Tester();
console.log(t1.test === t2.test); // "false"
请注意,您可以拥有实现专用的函数,但不分配给对象的任何实例。模块模式便于执行此操作:
var Tester = (function() {
function Tester(name) {
this.name = name;
}
Tester.prototype.publicFunction = function() {
privateFunction.call(this);
};
function privateFunction() {
console.log("My name is " + this.name);
}
return Tester;
})();
var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function
在那里,privateFunction
是完全私有的,只有匿名函数中的代码才能访问。它只有一个副本,但是您可以调用它,就像您使用privateFunction调用Tester
实例的方法一样。调用(this)
当然,另外,由于使用call
比执行普通调用稍慢,因此您可以将实例作为参数传递:
var Tester = (function() {
function Tester(name) {
this.name = name;
}
Tester.prototype.publicFunction = function() {
privateFunction(this);
};
function privateFunction(t) {
console.log("My name is " + t.name);
}
return Tester;
})();
var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function
当然,通话的额外费用
只有在出现问题时才是问题;除非你在一个紧密的循环中打了几十万次电话,否则这不太重要。因此,使用调用和此或传递参数主要是一种风格选择。我花了一段时间(来自ActionScript 3背景),但我觉得我应该与您分享;)
许多流行的JavaScript库,例如和,只是使用了一种命名约定,其中前导下划线表示私有成员,而不是使用稍微深奥的语法(尽管每个都有自己的语法!)。为了给它提供一些额外的上下文,Python的文档甚至说Python根本不支持私有成员
JavaScript是一种非常动态的语言;没有严格的类型检查和一些;还有一些非常酷的库,它们利用了这些事实,例如,它可以轻松地在代码库中实现有意义的测试覆盖率;例如:
var instance = new Car("ford");
// Replace the car's engine with test stub.
// Alternative syntax: sinon.stub(instance, '_engine');
instance._engine = sinon.stub(instance._engine);
car.start();
// As the '_engine' object has been mocked it gains new attributes.
ok(instance._engine.checkOil.calledOnce, 'Oil level was checked');
很抱歉,这个答案并没有真正回答您的问题(t.J的答案在这方面几乎是教科书式的)-我只是认为提供另一种可能的解决方案是值得的。您是否有任何证据证明可以重用?至少在Chrome18中,为创建的每个实例和函数创建了一个闭包对象,可以在堆屏幕截图中看到。@Esailija:我说的是底层代码,而不是上下文。上下文(和函数对象)必须在每次调用时创建(并且只要有未完成的引用就保留),除非进行没有外部副作用的优化。关于代码重用,一位v8开发人员告诉我,在v8邮件列表中,代码将被重用于源代码中相同位置定义的函数“……在大多数情况下……”,他预计(但实际上并不知道)大多数其他引擎也会这样做。例如,实现和上下文/功能对象是不同的。这是有道理的。@Esailija:终于找到了交换,我在这里已经提到过了。实际上,我想我会听从你的建议:TJ的答案正是我想要的答案,但他的解决方案有点太复杂,每次实例化时重新定义的成本有点太高,对于私人方法提供的低价值。这也是我得出的结论——我为此感到高兴;)