我已经编写了一个自定义组件来创建一个html按钮。自定义组件定义如下
dojo.provide("ovn.form.OvnButton") ;
require([ "dojo/_base/declare",
"dojo/dom-construct",
"dojo/parser",
"dojo/ready",
"dijit/_WidgetBase"],
function (declare, domConstruct, parser, ready, _WidgetBase){
return declare ("ovn.form.OvnButton",[_WidgetBase],{
label: "unknown",
constructor : function(args){
this.id = args.id;
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
});
alert("from constructor " + this.label);
},
postMixInProperties : function(){
},
buildRendering : function(){
alert("from renderer label is " + this.label);
this.domNode = domConstruct.create("button", { innerHTML: this.label }); //domConstruct.toDom('<button>' + this.label + '</button>');
},
_getLabelAttr: function(){
return this.label;
},
_setLabelAttr : function(label){
alert("from set input is " + label)
this.label = label;
},
postCreate : function(){
alert("Post create label is " + this.label);
},
startUP : function(){
}
});
});这就是我实例化组件的方式。
var button = new ovn.form.OvnButton({
id:'run',
props:[{"name":"label","value":"Run"},{"name":"class","value":"btn"}]
});在自定义组件的构造函数中,我迭代传递的数组并将其赋值给实例变量'label‘。令我惊讶的是,当我们在buildRendering函数中打印实例变量时,它仍然打印默认值而不是指定的值。
有人能解释一下为什么会这样。
FYI:我在控制台上得到以下消息序列:找到的标签运行2、构造函数未知3、呈现器标签未知4、设置输入未知5、Post创建标签未知
发布于 2014-10-09 11:16:55
这是因为在小forEach函数中,this实际上指向与OvnButton对象完全不同的东西。
Javascript的this关键字在这方面非常奇怪(实际上,它与Dojo没有任何关系)。您可以在这里更多地了解它的工作原理:http://howtonode.org/what-is-this。这是Javascript的一个非常基本的概念,与其他语言不同,因此值得您花时间熟悉它。
但是有各种不同的方法可以快速解决它,所以这里有几个!
使用正则for循环而不是forEach和回调
最简单的方法可能是使用正则for循环而不是带回调的forEach。
....
// args.props.forEach(function(prop) {
for(var i = 0, l = args.props.length; i < l; i++) {
var prop = args.props[i];
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}//); <-- no longer need the closing parenthesis这里需要注意的是,Javascript的this魔术只发生在函数调用上,所以在本例中,当我们只使用for循环时,this继续指向正确的东西。
..。或用于second的第二个thisArg参数
但也许您真的想要使用forEach。它实际上有第二个参数,通常称为thisArg。它告诉forEach确保this指向您在回调函数中选择的内容。所以你会这样做:
....
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}, this); // <--- notice we give forEach two arguments now,
// the callback function _and_ a "thisArg" value不过,我不太确定上面的方法在所有浏览器中都能正常运行,所以这里有另一种解决问题的方法:
..。或者使用临时的“自我”变量
我们将使一个临时变量等于this。人们通常将这样的变量称为self,但您可以任意命名它。这一点很重要:只有Javascript在回调函数中不同对待的是this关键字:
....
var self = this; //<--- we basically give `this` an alternative
// name to use inside the callback.
args.props.forEach(function(prop) {
if(prop.name == 'label'){
self.label = prop.value; //<--- replaced `this` with `self`
alert("found label " + self.label); //<--- here as well
}
});..。或使用dojo/_base/lang中的hitch()
有些人不喜欢self解决方案,可能是因为他们喜欢不断地使用this来引用拥有的对象。因此,许多框架都有一个"bind“函数,它确保函数总是在特定的作用域中调用。在dojo的例子中,这个函数被称为hitch。下面是如何使用它:
require([....., "dojo/_base/lang"], function(....., DojoLang) {
....
args.props.forEach(DojoLang.hitch(this, function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}));..。或者使用Javascript自己的bind()
Dojo和几乎所有其他框架都有一个hitch()函数。因为在Javascript中它是一个常用的概念,所以新的Javascript标准实际上引入了它自己的变体Function.prototype.bind()。你可以这样使用它:
....
args.props.forEach(function(prop) {
if(prop.name == 'label'){
this.label = prop.value;
alert("found label " + this.label);
}
}.bind(this));这是一个很长的答案,一个相当小的事情,我希望这是有意义的!
https://stackoverflow.com/questions/26254739
复制相似问题