JS에서 특정 변수의 값이 변경 될 때 발생하는 이벤트를 가질 수 있습니까? JQuery가 허용됩니다.
답변
예, 이제 가능합니다!
나는이 오래된 스레드 알고 있지만 지금이 효과가 접근에게 (getter 및 setter)를 사용하여 가능하다 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
aInternal
필드 를 나타내는 다음 과 같은 객체를 정의 할 수 있습니다 a
.
x = {
aInternal: 10,
aListener: function(val) {},
set a(val) {
this.aInternal = val;
this.aListener(val);
},
get a() {
return this.aInternal;
},
registerListener: function(listener) {
this.aListener = listener;
}
}
그런 다음 다음을 사용하여 리스너를 등록 할 수 있습니다.
x.registerListener(function(val) {
alert("Someone changed the value of x.a to " + val);
});
따라서의 값이 변경 될 때마다 x.a
리스너 함수가 시작됩니다. 다음 줄을 실행하면 경고 팝업이 나타납니다.
x.a = 42;
https://jsfiddle.net/5o1wf1bn/1/ 의 예를 참조하십시오.
단일 리스너 슬롯 대신 리스너 배열을 사용할 수도 있지만 가장 간단한 예를 들었습니다.
답변
이 질문에 대한 대부분의 답변은 오래되었거나 비효율적이거나 큰 부풀린 라이브러리를 포함해야합니다.
- Object.watch 및 Object.observe 는 더 이상 사용되지 않으며 사용해서는 안됩니다.
- onPropertyChange 는 일부 IE 버전에서만 작동하는 DOM 요소 이벤트 핸들러입니다.
- Object.defineProperty를 사용하면 객체 속성을 변경할 수 없도록하여 시도한 변경 사항을 감지 할 수 있지만 변경 사항도 차단할 수 있습니다.
- setter 및 getter 정의 는 작동하지만 많은 설정 코드가 필요하며 새 특성을 삭제하거나 작성해야 할 때 제대로 작동하지 않습니다.
오늘, 당신은 지금 사용할 수있는 프록시 객체 객체에 대한 변경 모니터 (와 절편)에 있습니다. OP가하려는 일을 위해 만들어진 것입니다. 기본 예는 다음과 같습니다.
var targetObj = {};
var targetProxy = new Proxy(targetObj, {
set: function (target, key, value) {
console.log(`${key} set to ${value}`);
target[key] = value;
return true;
}
});
targetProxy.hello_world = "test"; // console: 'hello_world set to test'
Proxy
객체 의 유일한 단점은 다음 과 같습니다.
Proxy
객체 (예 : IE11 등) 이전 버전의 브라우저에서 사용할 수 없습니다와 polyfill 수 완전히 복제되지Proxy
기능을 제공합니다.- 프록시 객체는 항상 특수 객체 (예 :)에서 예상대로 작동하지는 않습니다
Date
.Proxy
객체는 일반 객체 또는 배열과 가장 잘 어울립니다.
중첩 된 객체의 변경 사항을 관찰 해야하는 경우 Observable Slim (내가 게시 한) 과 같은 특수 라이브러리를 사용해야합니다 .
var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
console.log(JSON.stringify(changes));
});
p.testing.blah = 42; // console: [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
답변
아니.
그러나 그것이 정말로 중요하다면, 두 가지 옵션이 있습니다 (첫 번째는 테스트되고 두 번째는 그렇지 않습니다)
먼저 setter와 getter를 사용하십시오.
var myobj = {a : 1};
function create_gets_sets(obj) { // make this a framework/global function
var proxy = {}
for ( var i in obj ) {
if (obj.hasOwnProperty(i)) {
var k = i;
proxy["set_"+i] = function (val) { this[k] = val; };
proxy["get_"+i] = function () { return this[k]; };
}
}
for (var i in proxy) {
if (proxy.hasOwnProperty(i)) {
obj[i] = proxy[i];
}
}
}
create_gets_sets(myobj);
다음과 같은 것을 할 수 있습니다 :
function listen_to(obj, prop, handler) {
var current_setter = obj["set_" + prop];
var old_val = obj["get_" + prop]();
obj["set_" + prop] = function(val) { current_setter.apply(obj, [old_val, val]); handler(val));
}
그런 다음 리스너를 다음과 같이 설정하십시오.
listen_to(myobj, "a", function(oldval, newval) {
alert("old : " + oldval + " new : " + newval);
}
둘째, 실제로 잊어 버렸습니다. 생각하는 동안 제출하겠습니다 🙂
편집 : 아, 나는 기억한다 🙂 당신은 가치에 시계를 넣을 수 있었다 :
위에 myobj가 주어지면 ‘a’가 표시됩니다.
function watch(obj, prop, handler) { // make this a framework/global function
var currval = obj[prop];
function callback() {
if (obj[prop] != currval) {
var temp = currval;
currval = obj[prop];
handler(temp, currval);
}
}
return callback;
}
var myhandler = function (oldval, newval) {
//do something
};
var intervalH = setInterval(watch(myobj, "a", myhandler), 100);
myobj.set_a(2);
답변
사용 Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
// Console
function print(t) {
var c = document.getElementById('console');
c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var myVar = 123;
Object.defineProperty(this, 'varWatch', {
get: function () { return myVar; },
set: function (v) {
myVar = v;
print('Value changed! New value: ' + v);
}
});
print(varWatch);
varWatch = 456;
print(varWatch);
<pre id="console">
</pre>
다른 예
// Console
function print(t) {
var c = document.getElementById('console');
c.innerHTML = c.innerHTML + '<br />' + t;
}
// Demo
var varw = (function (context) {
return function (varName, varValue) {
var value = varValue;
Object.defineProperty(context, varName, {
get: function () { return value; },
set: function (v) {
value = v;
print('Value changed! New value: ' + value);
}
});
};
})(window);
varw('varWatch'); // Declare
print(varWatch);
varWatch = 456;
print(varWatch);
print('---');
varw('otherVarWatch', 123); // Declare with initial value
print(otherVarWatch);
otherVarWatch = 789;
print(otherVarWatch);
<pre id="console">
</pre>
답변
오래된 스레드를 가져 와서 죄송하지만 여기에 나와 같은 Eli Grey의 예제가 어떻게 작동하는지 보지 못하는 사람들을위한 약간의 매뉴얼이 있습니다.
var test = new Object();
test.watch("elem", function(prop,oldval,newval){
//Your code
return newval;
});
이것이 누군가를 도울 수 있기를 바랍니다.
답변
으로 누가 쉐퍼의 대답 ( 참고 :이 그의 원래의 게시물을 의미 있지만 요점은 여기에 편집 후 유효 ), 나 또한 가져 오기 한 쌍의 / 당신의 가치를 액세스 할 수있는 설정 방법을 제안합니다.
그러나 나는 약간의 수정을 제안 할 것입니다 (그리고 그것이 내가 게시하는 이유입니다 …).
이 코드의 문제점 a
은 객체 의 필드 에 myobj
직접 액세스 할 수 있으므로 리스너를 트리거하지 않고 객체 에 액세스하거나 값을 변경할 수 있다는 것입니다.
var myobj = { a : 5, get_a : function() { return this.a;}, set_a : function(val) { this.a = val; }}
/* add listeners ... */
myobj.a = 10; // no listeners called!
캡슐화
따라서 리스너가 실제로 호출되도록하려면 해당 필드에 대한 직접 액세스를 금지해야합니다 a
. 그렇게하는 방법? 폐쇄를 사용하십시오 !
var myobj = (function() { // Anonymous function to create scope.
var a = 5; // 'a' is local to this function
// and cannot be directly accessed from outside
// this anonymous function's scope
return {
get_a : function() { return a; }, // These functions are closures:
set_a : function(val) { a = val; } // they keep reference to
// something ('a') that was on scope
// where they were defined
};
})();
이제 Luke가 제안한 것과 동일한 방법으로 리스너를 작성하고 추가 할 수 있지만 a
눈에 띄지 않게 읽거나 쓸 수있는 방법은 없습니다 .
프로그래밍 방식으로 캡슐화 된 필드 추가
여전히 Luke의 트랙에서 간단한 함수 호출을 통해 캡슐화 된 필드와 해당 getter / setter를 객체에 추가하는 간단한 방법을 제안합니다.
이것은 값 유형 에서만 올바르게 작동 합니다 . 와 작업이 들어 참조 형식 , 어떤 종류의 깊은 복사 (참조 구현되어야 할 것입니다 이 하나를 예를 들어).
function addProperty(obj, name, initial) {
var field = initial;
obj["get_" + name] = function() { return field; }
obj["set_" + name] = function(val) { field = val; }
}
이것은 이전과 동일하게 작동합니다. 함수에 로컬 변수를 만든 다음 클로저를 만듭니다.
사용 방법? 단순한:
var myobj = {};
addProperty(myobj, "total", 0);
window.alert(myobj.get_total() == 0);
myobj.set_total(10);
window.alert(myobj.get_total() == 10);
답변
jQuery {UI} (모든 사람이 :-)를 사용해야하는 경우 숨겨진 <input /> 요소와 함께 .change ()를 사용할 수 있습니다.