构造函数中的变量集在不同的方法中未定义
Variable set in constructor is undefined in different method
我正在使用 Google 地图在 CoffeeScript 中创建一个库来计算票价。
像这样初始化地图时:
var viewport = document.getElementById('viewport'),
options = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
google.maps.event.addDomListener(window, 'load', function()
{
var map = new google.maps.Map(viewport, options);
});
它按预期加载。
但是当我使用我的库初始化它时:
var viewport = document.getElementById('viewport'),
options = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
},
map = new FareJS.Map(viewport, options);
视口保持灰色,四处移动地图得到 TypeError: a is undefined
。
稍微研究了一下,发现Map
class中的方法initializeMap
中@opt
的值未定义。我觉得很奇怪,因为我在构造函数中设置了它。陌生人仍然是 @viewport
是 而不是 未定义...只是 @opt
.
有问题的class是
class Map
constructor: (@viewport, @opt) ->
if not window.hasOwnProperty('google')
throw "Google Maps API could not be found, are you sure you installed it?"
@loadMapOnLoad()
initializeMap: () ->
@map = new google.maps.Map(@viewport, @opt)
return
loadMapOnLoad: () ->
google.maps.event.addDomListener(window, 'load', @initializeMap)
return
编译后如下所示:
var Map;
Map = (function() {
function Map(viewport, opt) {
this.viewport = viewport;
this.opt = opt;
if (!window.hasOwnProperty('google')) {
throw "Google Maps API could not be found, are you sure you installed it?";
}
this.loadMapOnLoad();
}
Map.prototype.initializeMap = function() {
this.map = new google.maps.Map(this.viewport, this.opt);
};
Map.prototype.loadMapOnLoad = function() {
google.maps.event.addDomListener(window, 'load', this.initializeMap);
};
return Map;
})();
为什么会这样,我该如何解决?
问题是 initializeMap
将在您 class/object 的上下文之外执行。 this
不会在 initializeMap
中引用您的 class 实例。您必须执行以下操作之一:
# explicitly bind to @
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
google.maps.event.addDomListener window, 'load', @initializeMap.bind @
# preserve context with => and call regularly
google.maps.event.addDomListener window, 'load', => @initializeMap()
# declare method with bound context, so it doesn't matter how you call it
# (resulting behaviour could be considered somewhat unidiomatic for JS, caveat emptor)
class Map
initializeMap: =>
..
我正在使用 Google 地图在 CoffeeScript 中创建一个库来计算票价。
像这样初始化地图时:
var viewport = document.getElementById('viewport'),
options = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
google.maps.event.addDomListener(window, 'load', function()
{
var map = new google.maps.Map(viewport, options);
});
它按预期加载。
但是当我使用我的库初始化它时:
var viewport = document.getElementById('viewport'),
options = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
},
map = new FareJS.Map(viewport, options);
视口保持灰色,四处移动地图得到 TypeError: a is undefined
。
稍微研究了一下,发现Map
class中的方法initializeMap
中@opt
的值未定义。我觉得很奇怪,因为我在构造函数中设置了它。陌生人仍然是 @viewport
是 而不是 未定义...只是 @opt
.
有问题的class是
class Map
constructor: (@viewport, @opt) ->
if not window.hasOwnProperty('google')
throw "Google Maps API could not be found, are you sure you installed it?"
@loadMapOnLoad()
initializeMap: () ->
@map = new google.maps.Map(@viewport, @opt)
return
loadMapOnLoad: () ->
google.maps.event.addDomListener(window, 'load', @initializeMap)
return
编译后如下所示:
var Map;
Map = (function() {
function Map(viewport, opt) {
this.viewport = viewport;
this.opt = opt;
if (!window.hasOwnProperty('google')) {
throw "Google Maps API could not be found, are you sure you installed it?";
}
this.loadMapOnLoad();
}
Map.prototype.initializeMap = function() {
this.map = new google.maps.Map(this.viewport, this.opt);
};
Map.prototype.loadMapOnLoad = function() {
google.maps.event.addDomListener(window, 'load', this.initializeMap);
};
return Map;
})();
为什么会这样,我该如何解决?
问题是 initializeMap
将在您 class/object 的上下文之外执行。 this
不会在 initializeMap
中引用您的 class 实例。您必须执行以下操作之一:
# explicitly bind to @
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
google.maps.event.addDomListener window, 'load', @initializeMap.bind @
# preserve context with => and call regularly
google.maps.event.addDomListener window, 'load', => @initializeMap()
# declare method with bound context, so it doesn't matter how you call it
# (resulting behaviour could be considered somewhat unidiomatic for JS, caveat emptor)
class Map
initializeMap: =>
..