Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS私有方法未在每次构造函数调用时重新定义_Javascript_Oop_Private_Micro Optimization - Fatal编程技术网

Javascript 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");

如何使Javascript私有方法在每次调用构造函数时都不会重新定义

据我所知,在OOP-JS中,私有方法是在“类”的“构造函数方法”中定义的方法,每次实例化一个新的“对象”时调用。我在想也许函数声明(即
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的答案正是我想要的答案,但他的解决方案有点太复杂,每次实例化时重新定义的成本有点太高,对于私人方法提供的低价值。这也是我得出的结论——我为此感到高兴;)