2017-01-29 26 views
2

海兰我写的JS和HTML一个快速和肮脏的列表的用户界面,可以过滤: https://jsfiddle.net/maxbit89/2jab4fa4/找到了JavaScript Setter错误?

所以这种用法是这样的(小提琴行:96):

var list = new ui_list(document.body, 200, 300, "Test"); 
var encoder = function(dom, value) { 
    console.log("begin encoding"); 
    console.log(value) 
    dom.innerHTML = value.n; 
} 

list.add({'n': 1}, function() { 
    this.value.n++; 
    console.log(this.value.n); 
// this.value = this.value; 
}, encoder); 

那么什么这basicaly确实是创建列表,并增加了一个元素它具有一个对象:{“n”个:1}作为值和onClickHandler(上list.add第二参数)至极应由1(小提琴线增加值: 104)

但它不会做到这一点,直到您取消注释在拨弄线106。 (使用FireFox 50.1.0和Edge浏览器进行测试)

有没有任何机构知道为什么js的行为如此呢? 在一个多simplier例如,这工作得很好:

var myObj= { 
    'onvalueChange' : function() { 
     console.log('value changed'); 
    }, 
    'print' : function() { 
      console.log('value:'); 
     console.log(this.value); 
     console.log(this.value.n); 
    } 
}; 

Object.defineProperty(myObj, "value", { 
    get: function() { return this._value; }, 
    set: function(value) { 
     this.onvalueChange(); 
     this._value = value; 
    } 
}); 

myObj.value = {'n' : 1}; 

myObj.value.n++; 

myObj.print(); 
+0

你只能“看”属性一层深;更改为子属性不使用的setter /吸气 – dandavis

回答

3

首先,你必须这样定义的setter:

set: function (value) { 
    this.encoder(this, value); 
    this._value = value; 
} 

这意味着每次值设置,编码器将被调用用新值更新等效的DOM元素。

但随后事件监听器函数内你有:

function() { 
    this.value.n++; 
    console.log(this.value.n); 
    //this.value = this.value; 
} 

,你认为this.value.n++被设定值(意味着它调用这意味着编码器将被调用,以更新的DOM元素的setter)。但事实并非如此。 this.value.n++实际上是调用的getter。为了解释这更多:

this.value.n++; 

是一样的:

var t = this.value; // call the getter 
t.n++; // neither call the getter nor the setter. It just uses the reference (to the object) returned by the getter to set n 

所以,当你取消对该行this.value = this.value;,二传手被调用,而编码器被调用来更新DOM元素。

因此,要解决你的问题之一:

  • 让getter中调用编码器像你一样的二传手(但这种方法是非常哈克,因为它会更新DOM元素即使没有设置任何设置,每次获得呼叫)。
  • 更改这个this.value.n++;实际上调用setter,如:this.value = {n: this.value.n + 1};(但这也是hacky,如果值有很多键 - 值对,那么你必须在这里设置它们,以设置n)。
  • 调用事件监听器内部的编码器,这将是最好的方法(或者如果你不想传递参数给另一个函数(例如this.callEncoder()),它会调用它并[你]调用这个新的函数代替了事件监听器)。
+0

扎实的分析和一个很好的答案。 – Amy

+0

好吧,这是一个奇怪的行为:如果有人遇到同样的问题,这里是一个小例子:https:// jsfiddle。net/maxbit89/ehf3mzhn/ – maxbit89

+0

*奇怪的行为我的意思是它可能是无用的,因为你不能真正在框架中使用这个,当一个“最终用户”不知道如果有一个getter/setter涉及,他遇到了这个问题?。 – maxbit89