我偶然发现了一个我无法理解的问题,我希望这里的一些聪明人可能会启发我: - )
使用RequireJs的以下CoffeeScript给我一个范围问题。它可以与我们的老朋友Internet Explorer(即使是最新版本)中的任何其他浏览器完美配合。
问题是this.stop()
,或者更确切地说只是this
在Internet Explorer中为window
提供了window.stop()
以及在其他浏览器中所有代码都存在的对象。
因此Internet Explorer尝试stop()
,这显然不会起作用。虽然其他浏览器只是在范围内运行.push()
方法。这是为什么?
是否与在Internet Explorer中以其他方式工作的Array原型函数define ['require', 'cs!scroller', 'cs!router', 'jquery', 'cs!menu', 'cs!magicbox', 'newsflash', 'swiper', 'time', 'cs!ads'], (require, Scroller, Router, $, Menu, Magicbox, Newsflash, Swiper, Time) ->
start: ->
Router.addRouterEvents()
window.Looper = []
window.Looper.push () ->
[this.stop(), Router.start(), Scroller.start(), Newsflash(), Swiper(), Time()]
for func in window.Looper
func()
stop: ->
$('*').off()
有关?或者它只是一个错误?请赐教?
// Generated by CoffeeScript 1.7.1
(function() {
define(['require', 'cs!scroller', 'cs!router', 'jquery', 'cs!menu', 'cs!magicbox', 'newsflash', 'swiper', 'time', 'cs!ads'], function(require, Scroller, Router, $, Menu, Magicbox, Newsflash, Swiper, Time) {
return {
start: function() {
var func, _i, _len, _ref, _results;
Router.addRouterEvents();
window.Looper = [];
window.Looper.push(function() {
return [this.stop(), Router.start(), Scroller.start(), Newsflash(), Swiper(), Time()];
});
_ref = window.Looper;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
func = _ref[_i];
_results.push(func());
}
return _results;
},
stop: function() {
return $('*').off();
}
};
});
}).call(this);
以下是编译为JavaScript的相同代码(对于我们熟悉的较少的CoffeeScript,因为除了问题在于CoffeeScript本身,我不会这样做):
{{1}}
答案 0 :(得分:2)
我没有运行你的代码,但我打赌你在所有平台上确实存在相同的基本问题。当您执行Looper
数组上的功能时,它们始终会window
作为this
的值。
问题是window
在多个平台上有stop
方法但在IE上没有。 (This是我这样说的来源。)因此,当您在IE上运行时,您会立即收到错误消息。在其他平台上,您可以拨打window.stop()
,这不是您想要的。对于踢,我在Chrome中运行了这个,没有错误:
(function () { this.stop() })()
您可以使用this
将bind
设置为所需的值。它在JavaScript中看起来像这样:
window.Looper.push(function() {
return [this.stop(), Router.start(), Scroller.start(), Newsflash(), Swiper(), Time()];
}.bind(this));
(注意匿名函数末尾的.bind(this)
。)
我建议您在"use strict";
的匿名函数的开头添加define
。它使得JavaScript在更健全的语义下运行,而不是没有它,并且这有助于在此找到问题,因为this
应该是undefined
而不是设置为window
。
答案 1 :(得分:1)
window.Looper.push(function() {
return [...];
});
然后在此执行此单一功能:
_results.push(func());
然后执行此功能:
function() {
return [this.stop(), Router.start(), Scroller.start(), Newsflash(), Swiper(), Time()];
}
返回在添加到数组时执行的函数数组。所以你的循环并没有真正实现任何目标,因为在这个设置中你需要做的就是忘记_i循环,而是调用:
window.Looper[0]()
执行函数数组中的所有内容。
所以这个函数调用序列看起来很复杂,我相信你会遇到范围问题。我不完全确定,但鉴于this.stop()正在执行window.Looper0返回一个匿名函数,我原本认为范围将成为所有浏览器的窗口 - 我很困惑至于这段代码是如何工作的! EG,这是一个简化版本,显示了这个&#39;的价值。当你调用this.stop()确实是窗口时:
可能需要/ js正在做一些魔术让它工作,我无法在repl.it片段中模拟。无论哪种方式,我认为解决方案是JavaScript将简化为简化:
window.Looper = [this.stop, Router.start, Scroller.start, Newsflash, Swiper, Time]
即,可以循环和调用的函数引用数组。这是一个例子,显示了没有require.js的这个概念和一个Router.start的存根:
我认为相应的咖啡脚本将是:
define ['require', 'cs!scroller', 'cs!router', 'jquery', 'cs!menu', 'cs!magicbox', 'newsflash', 'swiper', 'time', 'cs!ads'], (require, Scroller, Router, $, Menu, Magicbox, Newsflash, Swiper, Time) ->
start: ->
Router.addRouterEvents()
// Push funcs into the array, in case there is already something there (see comments)
// Probably a nicer way of doing this in CoffeeScript
// in JS I'd do window.Looper.push.apply(window.Looper, [func, func])
window.Looper.push(this.stop)
window.Looper.push(Router.start)
window.Looper.push(Scroller.start)
window.Looper.push(Newsflash)
window.Looper.push(Swiper)
window.Looper.push(Time)
for func in window.Looper
func()
stop: ->
$('*').off()