Javascript 关于使用jQuery悬停方法时的闭包?

Javascript 关于使用jQuery悬停方法时的闭包?,javascript,jquery,Javascript,Jquery,我的代码: function Demo (){ this.name = 'abc'; this.age = 20; } var demo = { init : function(){ $('#test').hover(this.stop, this.start); }, start: function(){ //here is the error alert(this.name); } stop: function(){ aler

我的代码:

function Demo (){
  this.name = 'abc';
  this.age = 20;
}

var demo = {
  init : function(){
    $('#test').hover(this.stop, this.start);
  },

  start: function(){
    //here is the error
    alert(this.name);
  }

  stop: function(){
    alert(this.age); // 'this' does not mean the Demo object, but $('#test') object.
  }
}

Demo.prototype = demo;
Demo.prototype.constructor = Demo;

(new Demo).init();
触发$('#test')的悬停事件时,将调用stop方法。但是,方法中的“this”并不指向demo对象,而是指向$(“#test”)对象。因此,警报未定义。我需要访问演示对象中的属性。停止和启动方法将在其他地方重用,因此我不喜欢将整个方法代码写入hover的参数中。
如何解决此问题?

start
stop
方法中的
this
不一定指向与
init
中相同的
this
。这是因为它们是回调函数。如果要引用相同的对象上下文,请尝试以下操作:

var demo = {
  init : function(){
    $('#test').hover(this.stop.bind(this), this.start.bind(this));
  },

  start: function(){
    //here is the error
    alert(this.name);
  }

  stop: function(){
    alert(this.age); // 'this' does not mean the Demo object, but $('#test') object.
  }
}
使用
bind
上下文传递给回调。 JQuery使用幕后调用事件回调,这就是上下文更改的原因

要缓解此问题,您可以执行以下两种操作之一:

使用

直接调用该方法

var demo = {
  init : function(){
    // Closure here
    var self = this;
    $('#test').hover(function() {
        self.stop();
    }, function() {
        self.start();
    });
  },

  start: function(){
    alert(this.name);
  }

  stop: function(){
    alert(this.age);
  }
}

一个无JSON实现,允许您设置变量self

function Demo(){
  this.name = 'abc';
  this.age = 20;
}

Demo.prototype = new (function(){
    var self = this;

    this.init = function(){
      $('#test').hover(self.stop, self.start);
    }

    this.start = function(){
      //here is the error
      alert(self.name);
    }

    this.stop = function(){
      alert(self.age); // 'this' does not mean the Demo object, but $('#test') object.
    }
  })();

(new Demo()).init()
编辑:
我已经更新以显示我在没有使用
var demo={…}
的情况下的意思,我试图说明的要点是不使用
Object Literal
aka JSON样式,这样您就可以支持原型中的变量,而不使用闭包。您有一个基于函数的对象和一个基于JSON的对象,其中没有一部分是闭包,但是为什么
(new Demo).init()您认为应该是
(新的Demo()).init()
因为Demo是一个返回对象的函数
Demo
这个问题的可能重复在这里已经被问过无数次了,以这样或那样的形式。问题的典型形式是“如何将对象方法作为回调参数传递给[setTimeout、$.ajax、Promise.then、$.on等]?为什么只传递
this.method
?”不起作用?基本原因是,无论谁回叫你,都不知道调用回调的
this
,所以你必须“绑定”以这样或那样的方式调用回调。作为一个复制品提出的问题只是这个问题的许多答案之一。你不能在一个对象中间声明一个变量。代码不是correct@MartinBarker我不明白你的评论。我的答案中JSON对象在哪里?你是说对象文字吗?
var demo={}
这是JSON,因为它使用
key:value,
这是JSONNo,JSON没有方法。这称为对象文字。它仍然是JavaScript对象符号,它与方法一起工作,因为函数在JavaScript中仍然是可变的。这里是我在chrome inspector控制台中运行的一个示例<代码>var hello=“hello”/*未定义的*/function hello(){return“hello”}/*未定义的*/console.log(hello)/*function hello(){return“hello”}未定义的*/
注释是控制台的返回值。您可以自己尝试此操作。虽然这与设置原型不完全相同。正如@davin tryon所指出的,问题不在于JSON实现,而在于对象文字谢谢@MartinBarker,我稍后会尝试你的方法。它需要比使用bind()更多的代码更改。
function Demo(){
  this.name = 'abc';
  this.age = 20;
}

Demo.prototype = new (function(){
    var self = this;

    this.init = function(){
      $('#test').hover(self.stop, self.start);
    }

    this.start = function(){
      //here is the error
      alert(self.name);
    }

    this.stop = function(){
      alert(self.age); // 'this' does not mean the Demo object, but $('#test') object.
    }
  })();

(new Demo()).init()