Функции, которые возвращают другие функции

Да, object.watch Редактировать, Джейсон по какой-то причине удалил свой пост, так что просто используйте запущена {* } Несмотря на поздний ответ, я обнаружил, что угловой UrlSearchParams работает очень хорошо для меня, он также заботится о кодировании параметров. , который работает во всех текущих основных браузерах.

Да, теперь это полностью возможно!

Я знаю, что это старая ветка, но теперь этот эффект возможен при использовании аксессоров (геттеров и сеттеров): , значение и аргументы предоставляются индивидуально.

и хотите включить дополнительные сценарии в область работника, остальные ответы предоставлены о добавлении сценариев в 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;

принимает список аргументов

, а

принимает

Сначала используйте сеттеры и геттеры, например:

, затем вы можете сделайте что-то вроде:

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);
}

принимает аргументы функции отдельно, и

Что такое «ценность» объекта? Это ссылка на объект.

.

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);

Мы можем дифференцировать вызов и применять методы, как показано ниже

принимает только два аргумента, один — теперь вы можете использовать Proxy объект Преимущество, которое я вижу в

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 object are:

  1. Переменная Proxy) обычно используется для нахождения индекса элемента в array.This также может быть использован для поиска объекта, но работает, только если вы передаете ссылку на тот же объект. где в качестве события указан объект json. не может полностью реплицироваться Proxy) —
  2. достигают того же самого, я думаю, что есть хотя бы одно место, где вы не можете использовать 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}}]

массивов Prototype: Резюме:

// 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>

Надеюсь, что это может кому-то помочь

var test = new Object();
test.watch("elem", function(prop,oldval,newval){
    //Your code
    return newval;
});

Надеюсь, это может кому-то помочь

: это относится к его первоначальному сообщению ;, но весь смысл здесь остается действительным после редактирования), я бы также предложил пару методов Get / Set для доступа к вашему значению. Ответ Люка Шефера ( Однако я бы предложил некоторые изменения (и именно поэтому я публикую …). объекта

Однако я бы посоветовал некоторые модификации (и именно поэтому я публикую …).

14 мая ’16 в 21:59 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
    };
})();

Теперь вы можете использовать тот же метод для создания и добавления слушателей, как предложил Люк, но вы можете быть уверены, что нет никакого способа читать или писать в a, оставаясь незамеченным!

php

Продолжая следить за Люком, я предлагаю теперь простой способ добавления инкапсулированных полей и соответствующих методов получения / установки к объектам с помощью простого вызова функции.

Обратите внимание, что это будет правильно работать только с типы значений . Для этого нужно работать с ссылочные типы , что-то вроде deep copy {* } OR EVEN SHORTER должно быть реализовано (см. этот , например).

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} (который должен использовать каждый :-)), вы можете использовать .change () со скрытым & Lt ; вводом / & Gt ; элемент.

AngularJS (я знаю, что это не JQuery, но это может помочь. [Чистый JS хорош только в теории]):

$scope.$watch('data', function(newValue) { ..

, где «data» — это имя вашей переменной в области.

Существует ссылка на документ.

Для настройки через пару лет:

доступно решение для большинства браузеров (и IE6), которое использует событие onpropertychange и более новую спецификацию defineProperty. Небольшая проблема в том, что вам нужно сделать вашу переменную объектом dom.

Полная информация:

http://johndyer.name/native-browser-get-set-properties-in-javascript/

Не напрямую: вам нужна пара getter / setter с каким-либо интерфейсом «addListener / removeListener» … или плагин NPAPI (но это совсем другая история).

Функциональность, которую вы ищете, может быть достигнута с помощью метода «defineProperty ()» — которая доступна только для современных браузеров:

Резюме:

Я написал расширение jQuery, которое имеет некоторые аналогичные функциональные возможности, если вам требуется дополнительная межбраузерная поддержка:

Когда первое и простое условие выполняется, интерпретатор пропускает следующие тесты.

Небольшое расширение jQuery, которое обрабатывает обратные вызовы в очереди для существование переменной, объекта или ключа. Вы можете назначить любое количество обратных вызовов любому количеству точек данных, на которые могут повлиять процессы, выполняющиеся в фоновом режиме. jQueue прослушивает и ожидает появления указанных вами данных, а затем запускает правильный обратный вызов со своими аргументами.

//ex:
/*
var x1 = {currentStatus:undefined};
your need is x1.currentStatus value is change trigger event ?
below the code is use try it.
*/
function statusChange(){
    console.log("x1.currentStatus_value_is_changed" x1.eventCurrentStatus);
};

var x1 = {
    eventCurrentStatus:undefined,
    get currentStatus(){
        return this.eventCurrentStatus;
    },
    set currentStatus(val){
        this.eventCurrentStatus=val;
      //your function();
    }
};

или

/*  var x1 = {
eventCurrentStatus:undefined,
currentStatus : {
    get : function(){
        return Events.eventCurrentStatus
        },
    set : function(status){
        Events.eventCurrentStatus=status;

    },
}*/
console.log("eventCurrentStatus = "  x1.eventCurrentStatus);
x1.currentStatus="create"
console.log("eventCurrentStatus = "  x1.eventCurrentStatus);
x1.currentStatus="edit"
console.log("eventCurrentStatus = "  x1.eventCurrentStatus);
console.log("currentStatus = "  x1.currentStatus);

или

/* global variable ku*/
    var jsVarEvents={};
    Object.defineProperty(window, "globalvar1", {//no i18n
        get: function() { return window.jsVarEvents.globalvarTemp},
        set: function(value) { window.window.jsVarEvents.globalvarTemp = value; }
    });
    console.log(globalvar1);
    globalvar1=1;
    console.log(globalvar1);

Довольно простое и простое решение — просто использовать вызов функции, чтобы установить значение глобальной переменной, и никогда не устанавливать ее значение напрямую. Таким образом, вы получаете полный контроль:

var globalVar;

function setGlobalVar(value) {
    globalVar = value;
    console.log("Value of globalVar set to: "   globalVar);
    //Whatever else
}

Нет никакого способа обеспечить это, просто требуется дисциплина программирования … хотя вы можете использовать grep (или что-то подобное), чтобы проверить, что нигде ваш код не устанавливает непосредственно значение globalVar Глядя на вывод

, или вы можете инкапсулировать это в объектных и пользовательских методах getter и setter … просто мысль.

Это напрямую невозможно.

Однако это можно сделать с помощью CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent

Приведенный ниже метод принимает массив имен переменных в качестве входных данных и добавляет прослушиватель событий для каждой переменной и запускает событие для любых изменений значения переменных.

Метод использует опрос для обнаружения изменения значения. Вы можете увеличить значение тайм-аута в миллисекундах.

function watchVariable(varsToWatch) {
    let timeout = 1000;
    let localCopyForVars = {};
    let pollForChange = function () {
        for (let varToWatch of varsToWatch) {
            if (localCopyForVars[varToWatch] !== window[varToWatch]) {
                let event = new CustomEvent('onVar_'   varToWatch   'Change', {
                    detail: {
                        name: varToWatch,
                        oldValue: localCopyForVars[varToWatch],
                        newValue: window[varToWatch]
                    }
                });
                document.dispatchEvent(event);
                localCopyForVars[varToWatch] = window[varToWatch];
            }
        }
        setTimeout(pollForChange, timeout);
    };
    let respondToNewValue = function (varData) {
        console.log("The value of the variable "   varData.name   " has been Changed from "   varData.oldValue   " to "   varData.newValue   "!!!"); 
    }
    for (let varToWatch of varsToWatch) {
        localCopyForVars[varToWatch] = window[varToWatch];
        document.addEventListener('onVar_'   varToWatch   'Change', function (e) {
            respondToNewValue(e.detail);
        });
    }
    setTimeout(pollForChange, timeout);
}

Вызывая Метод:

watchVariables(['username', 'userid']);

Он обнаружит изменения в переменных username и userid.

Это старый поток, но я наткнулся на второй по величине ответ (пользовательские слушатели), когда искал решение с использованием Angular. Несмотря на то, что решение работает, в Angular лучше встроен способ решения этой проблемы с помощью @Output PhantomJS

ChildComponent.html

<button (click)="increment(1)">Increment</button>

. Это момент времени (тики начиная с эпохи) с удобными функциями для перевода в и из строк в «местном» часовом поясе. Если вы хотите работать с датами, используя объекты даты, как это делают все здесь,

import {EventEmitter, Output } from '@angular/core';

@Output() myEmitter: EventEmitter<number> = new EventEmitter<number>();

private myValue: number = 0;

public increment(n: number){
  this.myValue  = n;

  // Send a change event to the emitter
  this.myEmitter.emit(this.myValue);
}

Без

<child-component (myEmitter)="monitorChanges($event)"></child-component>
<br/>
<label>{{n}}</label>

ParentComponent.ts

public n: number = 0;

public monitorChanges(n: number){
  this.n = n;
  console.log(n);
}

Это будет обновлять n Использование YUI stackblitz

Пожалуйста, ребята, помните, что первоначальный вопрос был для VARIABLES, а не для OBJECTS ;)

в HTML 4 и XHTML 1. Он не основан на SGML или XML ;, его синтаксис в основном касается с документированием и объединением реализаций. (Вот почему forTheWatch.js , которые используют тот же способ перехват и обратный вызов для изменений в нормальных глобальных переменных в JavaScript.

Совместим с переменными JQUERY, нет необходимости использовать OBJECTS, и вы можете при необходимости напрямую передавать массив из нескольких переменных.

имеет https://bitbucket.org/esabora/forthewatch
По сути, вам просто нужно вызвать функцию:
watchIt("theVariableToWatch", "varChangedFunctionCallback");

https://mootools.net/core/docs/1.6.0/Types/Object

Utils = {
    eventRegister_globalVariable : function(variableName,handlers){
        eventRegister_JsonVariable(this,variableName,handlers);
    },
    eventRegister_jsonVariable : function(jsonObj,variableName,handlers){
        if(jsonObj.eventRegisteredVariable === undefined) {
            jsonObj.eventRegisteredVariable={};//this Object is used for trigger event in javascript variable value changes ku
        }
        Object.defineProperty(jsonObj, variableName , {
                    get: function() { 
                        return jsonObj.eventRegisteredVariable[variableName] },
                    set: function(value) {
                        jsonObj.eventRegisteredVariable[variableName] = value; handlers(jsonObj.eventRegisteredVariable[variableName]);}
                    });
            }