【问题标题】:Javascript's object constructor's this.fn called without this possible?Javascript对象构造函数this.fn调用没有这个可能?
【发布时间】:2023-12-18 02:17:01
【问题描述】:

如果我通过new constructor() 调用创建一个对象,如下所示:

function constructor(){
    function privateFn(){
        console.log('this is private');
    }
    this.publicFn = function(){
        console.log('this is public');
    }
    function doSomething(){
        privateFn();
        publicFn();
    }
    console.log(this.publicFn ? "exists" : "does not exist"); // logs exists
    doSomething(); //throws an error -> publicFn() is not this.publicFn().
}
new constructor();

所以问题是,有没有办法在没有this. 部分的情况下使它可以访问? 即使没有 this.,我的 IDE(netbeans)似乎也能识别它,尽管这并不一定意味着什么,但它让我想知道,是否有可能以某种方式引用 publicFn() 作为函数,而不是作为目的?也许构造不同?

编辑: 目标是使用new 构造函数创建一个同时具有私有和公共方法的对象,但同时允许构造函数本身以及所有对象的方法调用没有 this. 前缀的公共方法。

BEKIM BACAJ 特别编辑

专门为您更新了此部分,只是为了向您展示我的意思。 这不是在欺骗我的 console.log,对 doSomething 的调用或在对象确实创建后出现的任何其他方法。虽然它仍然无法访问,现在我已经看到了为什么的答案,它是有道理的。私有方法的上下文this 不一样,或者构造函数中的函数将this 设置为窗口,因此它们的上下文this 与它们尝试调用的公共方法不同. Phylogenesis 建议的模式正是我所寻找的,并且符合需求。

function constructor(){
    function privateFn(){
        console.log('Call to privateFN succesful');
        console.log('------------------------------------------------------------------------------------');
    }
    function doSomething(){
        console.log('Executing: doSomething;');
        //I want to be able to access both private and public methods here (which i can)
        //I want to be able to access them the same way (which I cannot).
        privateFn(); //works
        publicFn(); //error 
        //Read NOTE1 below.
    }
    this.callDoSomething = function(){
        console.log('Call to callDoSomething succesful');
        console.log('------------------------------------------------------------------------------------');
        //made just so that you can access doSomething from the outside to test.
        doSomething();
    };
    this.publicFn = function(){
        console.log('Call to publicFN succesful');
        console.log('------------------------------------------------------------------------------------');
    };
    //.... many more methods (we are talking hundreds)
    //.... some of them are public, some are private
    //.... some are resutls of calling functions that return functions from other files (collaborative work), 
    //.... these might be public or private, which we achive like so:
    //.... var externalModule = extrenalModuleInitializer(this);
    //.... as you can imagine this externalModuleInitializer function can either:
    //.... A) PRIVATE: return a function, making this externalModule variable a private method
    //.... B) PUBLIC: do stuff with the `this` object that was passed, adding public methods to it
    //.... So since I do not know if certain parts of this object will be private or public, i need
    //.... a way to access them in the same way in order to make the coding easier.
}

console.clear();
var a = new constructor();
a.publicFn();
a.callDoSomething();

【问题讨论】:

  • 你的方法和代码本身都有问题
  • @BekimBacaj 然后解释一下什么是正确的方法
  • 目前还不清楚你在使用 new fn 时首先要做什么 - 没有这样的构造函数,而不是你调用的函数调用了一个还不存在的函数。
  • 构造函数中没有this的方法不能公开
  • 为什么要避免使用this

标签: javascript object this


【解决方案1】:

我认为你真正追求的是module pattern

function MyConstructor() {
  var publicFn = function () {
    console.log('this is public');
  }

  var privateFn = function () {
    console.log('this is private');
  }

  var doSomething = function () {
    privateFn();
    publicFn();
  }

  doSomething();

  return {
    publicFn: publicFn
  };
}

请注意您如何返回“公开”可访问方法的列表,但内部没有任何内容引用 this

here 就是一个例子。

【讨论】:

  • 正是我需要的。虽然我仍然只是附加 this.publicFn = publicFn; 并保留原始 this 的返回。这样对象才真正返回预期的 this 与构造函数,是吗?
  • 是的,如果你想使用隐式返回,那很好。但是请记住,这比处理原型的常规方法(将方法附加到原型本身而不是每个实例)稍微低效。
  • 太棒了。那么这正是我们所需要的。
  • @Dellirium 正如已经告诉你的那样,你根本不需要构造函数。这根本不是构造函数,这是一个普通的函数。
  • 公平地说,JavaScript 中的所有构造函数都只是普通函数。真正完成所有工作的是 new 运算符(返回被调用函数的 this 对象)。
【解决方案2】:

我不确定它是否符合您的需要,但是这个(末尾的 return 语句)公开了该方法:

function constructor(){ function privateFn(){ console.log('this is private'); } this.publicFn = function(){ console.log('this is public'); } function doSomething(){ privateFn(); publicFn(); } return{ publicFn: this.publicFn } }

你可以这样称呼它:

var constr = constructor(); constr.publicFn();

【讨论】:

  • 不符合我的需要,只要我用new 调用构造函数,该方法就会暴露出来,但我需要的是能够在构造函数(和其他函数)中引用该方法在构造函数的范围内)不使用this,我不确定是否可能。
【解决方案3】:

this 是对将根据您的函数描述的原型创建(但尚不存在)的对象的引用,因此在声明 public时不能避免 this 关键字> 方法。从技术上讲,您可以像这样在构造函数之外定义此函数:

function publicFn(){}

function constructor() {
  ....
}

var obj = new constructor();
obj.publicFn = publicFn;

但是,恐怕没有多大意义

【讨论】:

  • 但是如果要创建对象但不存在,我该如何执行以下操作:console.log(this.publicFn ? "exists" : "doesnt exist"); 并且在调用publicFn() 之前它会说“存在”(恰好抛出错误:SSS
  • 当您执行console.log(publicFn ? "exists" : "doesn't exist"); 时会发生什么?你在比较不同的东西。
  • 提供完整代码(你把console.log放在哪里了)
  • @dr_leevsey 我编辑了帖子以反映 console.log。我把它放在那里但删除了它,因为我认为它只会引起额外的混乱。 console.log 本身指出this.publicFndoSomething() 执行时确实存在。问题是,doSomething 没有对this.publicFn() 的引用,它试图使用publicFn 并且显然即使doSomething 的上下文与publicFn 的this 是同一个对象,它也认为不合适运行它。
  • @Phylogenesis 它实际上引发了一个不应该的参考错误,令我惊讶的是 o.0?我确信它会写“不存在”,但它没有。
【解决方案4】:

为了设计这个响应,我依赖于 Yves M.in this discussion 中提供的“使用自调用函数和调用”技术

var Constructor = (function (){

    function Constructor (){}

    function privateFn(){
        console.log('this is private');
    }

    Constructor.prototype.publicFn = function(){
        console.log('this is public');
        
    }
    Constructor.prototype.doSomething = function(){
        return privateFn.call(this);
    }
    
    return Constructor;
})();    

var Constructor = new Constructor();
Constructor.publicFn();
Constructor.doSomething();

注意:尽管空的构造函数方法看似什么都不做,但它对于代码运行无错误是必不可少的。否则,您将看到一条错误消息:“无法读取未定义的属性 'prototype'”,

使 privateFn() 方法隐藏的原因是它不是 Constructor 对象原型的一部分。此外,我能够在不提供 this 参数的情况下使 privateFn 的调用方法工作,但它是 call 方法签名的一部分。根据文档,忽略提供 this 会导致 null 和未定义的参数被“......替换为全局对象,原始值将被转换为对象。”

【讨论】:

  • 目标是在使用new 进行调用时创建的对象中隐藏私有并公开公共方法,同时仍然保留在不使用this. 的情况下在内部引用公共方法的可能性
  • @Dellirium 看看这是否有帮助。 Emulating private methods with closures
  • 是的,我知道闭包是如何工作的,整个constructor 确实在模拟私有方法,例如privateFn,因为它是一个闭包。但是(编辑了上面的帖子)我正在尝试使对象本身可以看到公共和私有成员(这是标准行为),而不像在对象中那样使用 this.,因为我们不应该被强迫来区分他们的呼叫。如果我们要讨论其他语言,在一个对象中,您可以以相同的方式调用私有成员和公共成员,只需 name(),公众不需要 this.name()
最近更新 更多