2011-03-18 46 views
0

我无法从Post.success函数中调用this.RenderDeals()。我认为这与范围有关?有人可以解释这个问题,并可能提出一种解决方法。我尝试过使用原型和模块模式,都没有任何运气。Javascript class scope

FYI Post是一个返回jQuery Deferred对象的$ .ajax包装器。

function Deals() { 
     this.template = '#trTemplate'; 
     this.container = '#containerTable'; 
     this.GetDeals = function() { 
      Post('Deal.svc/GetDeals') 
      .success(function (result) { 
       this.RenderDeals(result); 
      }); 
     }; 
     this.RenderDeals = function (deals) { 
      $(this.template).tmpl(deals).appendTo(this.container); 
     } 
    } 


    var deal = new Deals(); 
    deal.GetDeals(); 

UPDATE:

好了,所以我加了下面的行正上方GetDeals功能:

var me = this; 

,而是叫

me.RenderDeals(result); 

看似正常工作,但我不知道为什么。

+0

这是因为你已经定义'我'然后使用它。但直接使用'this'会给你一个别的事情的例子,因为你处于不同的上下文/范围中。 – Kon 2011-03-18 23:56:42

+0

只是一个仅供参考的东西,在javascript成语中,一个以大写字母开头的函数意味着它是一个构造函数。没有问题或任何东西,但它看起来很奇怪的人是一个JavaScript的人,但不是一个.net人 – 2011-03-18 23:56:51

+0

@Matt也许我会开始一场革命...... – 2011-03-19 00:34:24

回答

5

在你的 “成功” 功能this参考几乎肯定是不是你t它是。试试这个变化:

function Deals() { 
    var instance = this; 

    this.template = '#trTemplate'; 
    this.container = '#containerTable'; 
    this.GetDeals = function() { 
     Post('Deal.svc/GetDeals') 
     .success(function (result) { 
      instance.RenderDeals(result); 
     }); 
    }; 
    this.RenderDeals = function (deals) { 
     $(this.template).tmpl(deals).appendTo(this.container); 
    } 
} 

通过隐藏在“实例”变量this参考,您的处理器将具有调用其他功能(“RenderDeals”)时,又回到了相关实例的方式保证。

+1

yay关闭! +1 – 2011-03-18 23:53:13

+1

关闭。我会阅读。 – 2011-03-18 23:57:23

0

为什么不在Deals()之外定义RenderDeals()?

function RenderDeals(dealsObj, dealsData) { 
     $(dealsObj.template).tmpl(dealsData).appendTo(dealsObj.container); 
    } 

然后,而不是这样的:

this.RenderDeals(result); 

这样做:

RenderDeals(this, result); 
+0

因为我试图封装功能在一个类。 – 2011-03-18 23:52:27

+0

也许他不希望它是全球可见的? – Pointy 2011-03-18 23:53:08

+0

对不起,这并不明显,因为它没有在问题中指定。 – Kon 2011-03-18 23:57:00

0

试试这个:

var Deals = { 
    template: $('#trTemplate'), 
    container: $('#containerTable'), 
    init: function(){ 
     return Deals; 
    } 
    GetDeals: function() { 
     Post('Deal.svc/GetDeals') 
     .success(function (result) { 
      Deals.RenderDeals(result); 
     }) 
    }, 
    RenderDeals = function (deals) { 
     Deals.template.tmpl(deals).appendTo(Deals.container); 
    } 
} 

var deal = Deals.init(); 
deal.GetDeals(); 
+0

也许他真的想要构建许多这样的实例。 – Pointy 2011-03-18 23:53:41

+0

这会起作用,但通过使用闭包来捕获这个值,imo尖端有更好的答案。 – 2011-03-18 23:54:13

+0

是的,这是有道理的 – Adam 2011-03-18 23:55:32

0

你是对的,这是一个范围界定问题。波蒂有正确的答案,但我认为我可以填补一些正在发生的事情。

this在JavaScript中是一个隐式变量,它被设置为默认情况下函数所附加的任何内容(或者全局对象,如果它不附加任何东西)。当您将函数作为参数传递给Post#成功时,它不会附加到任何实例,更不用说当前的Deals实例。

Pointy在这里有最好的答案,他正在做的是创建一个显式变量,捕获交易的隐含变量this。 javascript最酷的功能之一是,函数定义范围内的所有内容都将在函数调用的范围内,因此通过创建该变量,您可以稍后再次访问它,无论何时何地匿名函数是调用。

2

首先,在javascript中没有类,只有对象。这听起来很奇怪,但是你仍然可以在没有javascript的情况下做OOP :)我建议你阅读这个。

你对范围问题是正确的,this关键字有一些奇怪的行为。请阅读this了解更多信息。

使用任何函数对象的prototype属性进行研究。我喜欢做我的javascript以下列方式OOP:

function Deals(){ 
    //this is your constructor 
    var me = this; 
    //this way you can avoid having to search the DOM every time you want to reference 
    //your jquery objects. 
    me.template = $('#trTemplate'); 
    me.container = $('#containerTable'); 
} 
Deals.prototype.getDeals = function(){ 
    var me = this; 
    Post('Deal.svc/GetDeals') 
    .success(function (result) { 
     me.RenderDeals(result); 
    }) 
} 
Deals.prototype.renderDeals = function(){ 
    var me = this; 
    me.template.tmpl(deals).appendTo(me.container); 
} 

通过在每个原型函数的顶部声明var me = this;,您可以创建一个指向感兴趣的对象封闭,甚至内部的回调:)

+0

哦,是的,忘了提到你会使用这样的Deals对象:'var deals = new Deals(); deals.renderDeals();' – Hersheezy 2011-03-19 00:04:52

+0

感谢您的替代模式。说实话,我不知道我是否真的需要这样做。我永远不会需要这个对象的许多实例,我只是试图封装一个特定的页面功能,使它更清洁,更易于管理。 – 2011-03-19 00:26:22