【问题标题】:Scope within an object literal对象字面量内的范围
【发布时间】:2010-09-10 12:47:06
【问题描述】:

我将从一个示例 sn-p 开始:

self.addwidget({
    box:    ns.box({                        
                text:       'Foobar',
                fromTop:    ~~(Math.random()*window.innerHeight),
                fromLeft:   ~~(Math.random()*window.innerWidth),
                toTop:      240,
                toLeft:     40,
                css:        'foobar',
                easing:     'easeOutCirc',
                duration:   2000,
                events:     {
                    mousedown:      function(e){
                        e.target.position = {x: e.pageX, y: e.pageY};
                    },
                    mouseup:        function(e){
                        // "this" should reference be "box"                                     
                    }
                }
    }),
    delay:  3000
});

简短描述
ns.box() 将对象作为参数并创建一个新的jQuery object。它使用jQuery.extend()events 属性对象与jQuery constructor $('<elem/>', {}); 合并
之后,ns.box() 返回一个包含一些方法的新对象。
--

我想要归档的是能够访问event handlers 中的那些propertys / methods。当然,此时我无法访问box.somemethod,因为此时我无法引用外部box 属性。所以我尝试将事件处理程序的范围从jQuery.proxy() 更改为this,但没有成功。
this.somemethod 即使在代理时也未被引用。 我还尝试从上到下代理所有对象,也没有成功。

在像这样的构造中,甚至有可能在事件处理程序中从ns.box() 的返回对象访问属性吗?

【问题讨论】:

  • 你真的必须使用~~吗?因为我很确定现在有人会过来问这意味着什么。 :) (james.padolsey.com/javascript/double-bitwise-not 如果你是其中之一)
  • @Yi:很抱歉,这只是我的代码转储。我不想在这里混淆任何人。您的链接应该澄清这一点,谢谢。
  • @蒋毅:很好的链接,谢谢。我喜欢他的断言“它更快”。几乎不可能用 JavaScript 做出如此全面的陈述,而在野外有各种各样的实现。 IE 上更快的东西在 FF 等上并不总是更快。
  • @T.J.同样重要的是要意识到在处理负数时它不等同于 Math.floor(),我不确定在那篇文章中强调的足够多。我确实喜欢使用像!!~~ 这样的成语,甚至只是+,而不是更冗长的方法,但那是因为我非常非常懒惰;-)

标签: javascript jquery scope


【解决方案1】:

您可以使用范围函数来实现这一点,如下所示:

self.addwidget((function() {
    var box = ns.box({                        
                text:       'Foobar',
                fromTop:    ~~(Math.random()*window.innerHeight),
                fromLeft:   ~~(Math.random()*window.innerWidth),
                toTop:      240,
                toLeft:     40,
                css:        'foobar',
                easing:     'easeOutCirc',
                duration:   2000,
                events:     {
                    mousedown:      function(e){
                        e.target.position = {x: e.pageX, y: e.pageY};
                    },
                    mouseup:        function(e){
                        // You can access `box` here                         
                    }
                }
    });

    return {
        box:   box,
        delay: 3000
    };
})());

通过将框分配给我们的作用域函数内的 var,我们创建了一个符号,事件处理程序(closures)关闭并因此可以访问。我们立即调用该函数,让它返回对象。闭包持有的引用是持久的,所以......

我一直使用这种模式,因为我不喜欢匿名函数(例如,您的事件处理程序是匿名的); more here。如果我执行上述操作,我会改为命名,如下所示:

self.addwidget((function() {
    var box = ns.box({                        
                text:       'Foobar',
                fromTop:    ~~(Math.random()*window.innerHeight),
                fromLeft:   ~~(Math.random()*window.innerWidth),
                toTop:      240,
                toLeft:     40,
                css:        'foobar',
                easing:     'easeOutCirc',
                duration:   2000,
                events:     {
                    mousedown:      boxMousedown,
                    mouseup:        boxMouseup
                }
    });

    function boxMousedown(e){
        e.target.position = {x: e.pageX, y: e.pageY};
    }

    function boxMouseup(e){
        // You can access `box` here                         
    }

    return {
        box:   box,
        delay: 3000
    };
})());

这些函数的名称现在可以显示在调用堆栈和错误消息中,但它们是完全私有的,不会弄乱全局命名空间。

【讨论】:

  • 确实,不错的建议 T.J.使用box 的闭包,我应该自己想通了。
  • @T.J.克劳德:~~() 是做什么的?
  • @Robusto:见蒋毅对该问题的评论中的链接。在我读之前我也不知道。 :-)
  • @T.J.:即使这个解决方案很棒,我仍然更喜欢在处理程序中访问box 而不是this。这只有应用程序逻辑原因。你能想出一种方法来实现它吗?甚至可能?
  • @jAndy:当然,这很简单:在我的第二个示例(使用命名函数的示例)中,将mousedown: boxMousedown 更改为mousedown: function(event) { return boxMousedown.call(box, event) }。它引入了一个额外的函数调用,但这不太可能成为 mousedown 和 mouseup 的大性能问题。唯一的另一种方法是 ns.box 背后的代码明确提供支持。
猜你喜欢
  • 2016-04-19
  • 2012-10-15
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 2011-04-25
  • 2021-02-01
  • 2020-12-21
  • 2013-05-29
相关资源
最近更新 更多