为了账号安全,请及时绑定邮箱和手机立即绑定

在JavaScript原型函数中保留对“此”的引用

在JavaScript原型函数中保留对“此”的引用

哔哔one 2019-07-03 16:52:29
在JavaScript原型函数中保留对“此”的引用我只是开始使用原型JavaScript,我很难找到如何保存this当作用域改变时,从原型函数中引用主对象。让我来解释一下我的意思(我在这里使用jQuery):MyClass = function() {   this.element = $('#element');   this.myValue = 'something';   // some more code}MyClass.prototype.myfunc = function() {   // at this point, "this" refers to the instance of MyClass   this.element.click(function() {     // at this point, "this" refers to the DOM element     // but what if I want to access the original "this.myValue"?   });}new MyClass();我知道,我可以保留对主对象的引用,方法是在myfunc:var myThis = this;然后使用myThis.myValue若要访问主对象的属性,请执行以下操作。但是当我有大量的原型函数时会发生什么?MyClass?我是否必须保存引用this在每一个开始的时候?看来应该有个更干净的方法。那么像这样的情况呢:MyClass = function() {   this.elements $('.elements');   this.myValue = 'something';   this.elements.each(this.doSomething);}MyClass.prototype.doSomething = function() {   // operate on the element}new MyClass();在这种情况下,我无法创建对主对象的引用var myThis = this;因为即使是this在.的范围内doSomething是jQuery对象,而不是MyClass对象。有人建议我使用一个全局变量来保存对原始this但对我来说这似乎是个坏主意。我不想污染全局名称空间,这似乎会阻止我实例化两个不同的名称空间。MyClass没有互相干扰的物体。有什么建议吗?有干净的方法做我想要做的事吗?还是我的整个设计模式都有缺陷?
查看完整描述

3 回答

?
饮歌长啸

TA贡献1951条经验 获得超3个赞

为你的最后一次MyClass例如,您可以这样做:

var myThis=this;this.elements.each(function() { myThis.doSomething.apply(myThis, arguments); });

在传递给eachthis引用jQuery对象,您已经知道了。如果在该函数中,您将获得doSomething功能来自myThis,然后使用参数数组调用该函数的Apply方法(请参阅apply功能arguments变量),那么this将被设置为myThis在……里面doSomething.


查看完整回答
反对 回复 2019-07-03
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

我意识到这是一个旧的线程,但我有一个更优雅的解决方案,除了我已经注意到的一般情况之外,它几乎没有什么缺点。

考虑以下几点:

var f=function(){
    var context=this;}    f.prototype.test=function(){
    return context;}    var fn=new f();fn.test(); // should return undefined because the prototype definition
    // took place outside the scope where 'context' is available

在上面的函数中,我们定义了一个局部变量(上下文)。然后,我们添加了一个返回局部变量的原型函数(Test)。正如您可能已经预测的,当我们创建这个函数的一个实例,然后执行测试方法时,它不会返回局部变量,因为当我们将原型函数定义为我们的主函数的成员时,它超出了定义局部变量的范围。这是一个常见的问题,需要创建函数,然后向其添加原型-您不能访问在主函数范围内创建的任何内容。

要创建局部变量范围内的方法,我们需要直接将它们定义为函数的成员,并去掉原型引用:

var f=function(){
    var context=this;    

    this.test=function(){
        console.log(context);
        return context;
    };}    var fn=new(f);fn.test(); //should return an object that correctly references 'this'//in the context of that function;    
    fn.test().test().test(); //proving that 'this' is the correct reference;

您可能担心,由于这些方法不是原型创建的,因此不同的实例可能并不真正是数据分离的。为了证明它们是这样的,请考虑以下几点:

var f=function(val){
    var self=this;
    this.chain=function(){
        return self;
    };    

    this.checkval=function(){
        return val;
    };}    var fn1=new f('first value');var fn2=new f('second value');    fn1.checkval();fn1.chain().chain().checkval();
    // returns 'first value' indicating that not only does the initiated value remain untouched,
    // one can use the internally stored context reference rigorously without losing sight of local variables.     
    fn2.checkval();fn2.chain().chain().checkval();// the fact that this set of tests returns 'second value'
    // proves that they are really referencing separate instances

使用此方法的另一种方法是创建单例。通常情况下,我们的javascript函数不会被实例化不止一次。如果您知道您永远不需要同一个函数的第二个实例,那么就有一种简单的方法来创建它们。不过,请注意:lint会抱怨这是一个奇怪的结构,并质疑您使用关键字“new”:

fn=new function(val){
    var self=this;
    this.chain=function(){
        return self;
    };        

    this.checkval=function(){
        return val;
    };  }    fn.checkval();fn.chain().chain().checkval();

专业人士:使用此方法创建函数对象的好处很多。

  • 它使您的代码更易于阅读,因为它缩进函数对象的方法,使其直观地更易于理解。
  • 它允许访问本地定义的变量。

    仅在最初以这种方式定义的方法中

    即使稍后向函数对象添加原型函数或成员函数,它也不能访问局部变量,而且您在该级别上存储的任何功能或数据在其他任何地方都是安全和不可访问的。
  • 它允许一种简单而直截了当的方式来定义单子。
  • 它允许您存储对“this”的引用,并无限期地维护该引用。

康:使用这种方法有一些缺点。我不假装是全面的:)


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 234 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信