JS私有方法未在每个构造函数调用时重新定义

时间:2012-05-05 15:23:15

标签: javascript oop private micro-optimization

如何在每次调用构造函数时都创建一个未重新定义的Javascript私有方法?

据我所知,在OOP-JS中,私有方法是在一个“类”的“构造函数方法”中定义的方法,每次实例化一个新的“对象”时调用。我想也许是一个函数声明(即function name(),而不是函数表达式var name = function())会做的伎俩,但我怎么能确定下面的代码只声明我的函数一次?

​function Tester() {
    function test () {
        console.log("executed");
    }
}
var t1 = new Tester();
var t2 = new Tester();

2 个答案:

答案 0 :(得分:4)

  

如何在每次调用构造函数时都创建一个未重新定义的Javascript私有方法?

你不能(好吧,请看下面的一些摆动空间)。但除非你有成千上万的{{​​1}}个实例,否则不要太担心;大多数引擎可能会在创建的多个函数对象中重用底层代码。 (代码,介意;不是函数对象或它关闭的上下文,必须每次都是唯一的和分配的。但它们不需要很大。当然,功能函数相当小......)

  

...我怎么能确定以下代码只声明我的函数一次?

你可以肯定它没有;它每次调用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调用Tester实例的方法。

或者,当然,因为使用privateFunction.call(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 的额外费用只是一个问题,如果它是一个问题;除非你在一个紧凑的循环中召唤成千上万次,否则不太重要。因此,是否使用callcall或传递参数主要是一种风格选择。

答案 1 :(得分:2)

我花了一段时间(来自ActionScript 3背景),但我觉得我应该与你分享how I learned to stop worrying and love the lack of private methods;)

许多流行的JavaScript库,例如Backbone.jsjs-Signals只是使用命名约定,其中前导下划线表示私有成员,而不是使用稍微深奥的语法(尽管每个都是自己的!) 。为了给出一些额外的上下文,Python的文档就是说Python根本不支持私有成员suggests using an underscore instead

JavaScript是一种非常动态语言;没有严格的类型检查和一些really exciting scoping;并且有一些非常酷的库可以利用这些事实,例如SinonJS,这使得在代码库中实现有意义的测试覆盖变得毫不费力;例如:

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的答案就是这方面的教科书) - 我只是觉得提供另一种可能的解决方案是值得的。