在javascript中,如何在变量值改变时触发事件? [重复]

时间:2021-05-22 15:23:08

This question already has an answer here:

这个问题在这里已有答案:

I have two variables:

我有两个变量:

var trafficLightIsGreen = false; 
var someoneIsRunningTheLight = false;

I would like to trigger an event when the two variables agree with my conditions:

当两个变量符合我的条件时,我想触发一个事件:

if(trafficLightIsGreen && !someoneIsRunningTheLight){
    go(); 
}

Assuming that those two booleans can change in any moment, how can I trigger my go() method when they change according to the my conditions?

假设这两个布尔值在任何时刻都可以改变,那么当他们根据我的条件改变时,如何触发我的go()方法呢?

7 个解决方案

#1


27  

There is no event which is raised when a given value is changed in Javascript. What you can do is provide a set of functions that wrap the specific values and generate events when they are called to modify the values.

在Javascript中更改给定值时,不会引发任何事件。您可以做的是提供一组函数,这些函数包含特定值并在调用它们时生成事件以修改值。

function Create(callback) {
  var isGreen = false;
  var isRunning = false;
  return { 
    getIsGreen   : function()  { return isGreen; },
    setIsGreen   : function(p) { isGreen = p; callback(isGreen, isRunning); },
    getIsRunning : function()  { return isRunning; },
    setIsRunning : function(p) { isRunning = p; callback(isGreen, isRunning); }
  };
}

Now you could call this function and link the callback to execute go():

现在你可以调用这个函数并链接回调来执行go():

var traffic = Create(function(isGreen, isRunning) {
  if (isGreen && !isRunning) {
    go();
  }
});

traffic.setIsGreen(true);

#2


2  

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

#3


1  

The most reliable way is to use setters like that:

最可靠的方法是使用这样的setter:

var trafficLightIsGreen = false; 
var someoneIsRunningTheLight = false;

var setTrafficLightIsGreen = function(val){
    trafficLightIsGreen = val;
    if (trafficLightIsGreen and !someoneIsRunningTheLight){
        go(); 
    };
};
var setSomeoneIsRunningTheLight = function(val){
    trafficLightIsGreen = val;
    if (trafficLightIsGreen and !someoneIsRunningTheLight){
        go(); 
    };
};

and then instead of assigning a value to a variable, you just invoke the setter:

然后,您只需调用setter,而不是为变量赋值:

setTrafficLightIsGreen(true);

#4


0  

There is no way to do it without polling with setInterval/Timeout.

没有使用setInterval / Timeout进行轮询,就无法做到这一点。

If you can support Firefox only, you can use https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

如果您只能支持Firefox,可以使用https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

Which will tell you when a property of an object changes.

这会告诉你对象的属性何时发生变化。

Your best solution is probably making them part of an object and adding getters, setters that you can send out notifications yourself, as JaredPar showed in his answer

你最好的解决方案可能是让它们成为一个对象的一部分并添加你自己可以发送通知的getter,setter,正如JaredPar在他的回答中所示

#5


0  

You could always have the variables be part of an object and then use a special function to modify the contents of it. or access them via window.

您始终可以将变量作为对象的一部分,然后使用特殊函数来修改它的内容。或通过窗口访问它们。

The following code can be used to fire custom events when values have been changed as long as you use the format changeIndex(myVars, 'variable', 5); as compared to variable = 5;

只要您使用格式changeIndex(myVars,'variable',5),以下代码可用于在更改值时触发自定义事件;与变量= 5相比;

Example:

例:

function changeIndex(obj, prop, value, orgProp) {
    if(typeof prop == 'string') { // Check to see if the prop is a string (first run)
        return changeIndex(obj, prop.split('.'), value, prop);
    } else if (prop.length === 1 && value !== undefined &&
               typeof obj[prop[0]] === typeof value) {
        // Check to see if the value of the passed argument matches the type of the current value
        // Send custom event that the value has changed
        var event = new CustomEvent('valueChanged', {'detail': {
                                                          prop : orgProp,
                                                          oldValue : obj[prop[0]],
                                                          newValue : value
                                                       }
                                                     });
        window.dispatchEvent(event); // Send the custom event to the window
        return obj[prop[0]] = value; // Set the value
    } else if(value === undefined || typeof obj[prop[0]] !== typeof value) {
        return;
    } else {
        // Recurse through the prop to get the correct property to change
        return changeIndex(obj[prop[0]], prop.slice(1), value);
    }
};
window.addEventListener('valueChanged', function(e) {
    console.log("The value has changed for: " + e.detail.prop);
});
var myVars = {};
myVars.trafficLightIsGreen = false;
myVars.someoneIsRunningTheLight = false;
myVars.driverName = "John";

changeIndex(myVars, 'driverName', "Paul"); // The value has changed for: driverName
changeIndex(myVars, 'trafficLightIsGreen', true); // The value has changed for: traggicIsGreen
changeIndex(myVars, 'trafficLightIsGreen', 'false'); // Error. Doesn't set any value

var carname = "Pontiac";
var carNumber = 4;
changeIndex(window, 'carname', "Honda"); // The value has changed for: carname
changeIndex(window, 'carNumber', 4); // The value has changed for: carNumber

If you always wanted to pull from the window object you can modify changeIndex to always set obj to be window.

如果您一直想从窗口对象中拉出,则可以修改changeIndex以始终将obj设置为窗口。

#6


0  

If you were willing to have about a 1 millisecond delay between checks, you could place

如果你愿意在两次检查之间有大约1毫秒的延迟,你可以放置

window.setInterval()

on it, for example this won't crash your browser:

例如,这不会导致浏览器崩溃:

window.setInterval(function() {
    if (trafficLightIsGreen && !someoneIsRunningTheLight) {
        go();
    }
}, 1);

#7


0  

function should_i_go_now() {
    if(trafficLightIsGreen && !someoneIsRunningTheLight) {
        go();
    } else {
        setTimeout(function(){
            should_i_go_now();
        },30);
    }
}
setTimeout(function(){
    should_i_go_now();
},30);

#1


27  

There is no event which is raised when a given value is changed in Javascript. What you can do is provide a set of functions that wrap the specific values and generate events when they are called to modify the values.

在Javascript中更改给定值时,不会引发任何事件。您可以做的是提供一组函数,这些函数包含特定值并在调用它们时生成事件以修改值。

function Create(callback) {
  var isGreen = false;
  var isRunning = false;
  return { 
    getIsGreen   : function()  { return isGreen; },
    setIsGreen   : function(p) { isGreen = p; callback(isGreen, isRunning); },
    getIsRunning : function()  { return isRunning; },
    setIsRunning : function(p) { isRunning = p; callback(isGreen, isRunning); }
  };
}

Now you could call this function and link the callback to execute go():

现在你可以调用这个函数并链接回调来执行go():

var traffic = Create(function(isGreen, isRunning) {
  if (isGreen && !isRunning) {
    go();
  }
});

traffic.setIsGreen(true);

#2


2  

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

#3


1  

The most reliable way is to use setters like that:

最可靠的方法是使用这样的setter:

var trafficLightIsGreen = false; 
var someoneIsRunningTheLight = false;

var setTrafficLightIsGreen = function(val){
    trafficLightIsGreen = val;
    if (trafficLightIsGreen and !someoneIsRunningTheLight){
        go(); 
    };
};
var setSomeoneIsRunningTheLight = function(val){
    trafficLightIsGreen = val;
    if (trafficLightIsGreen and !someoneIsRunningTheLight){
        go(); 
    };
};

and then instead of assigning a value to a variable, you just invoke the setter:

然后,您只需调用setter,而不是为变量赋值:

setTrafficLightIsGreen(true);

#4


0  

There is no way to do it without polling with setInterval/Timeout.

没有使用setInterval / Timeout进行轮询,就无法做到这一点。

If you can support Firefox only, you can use https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

如果您只能支持Firefox,可以使用https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

Which will tell you when a property of an object changes.

这会告诉你对象的属性何时发生变化。

Your best solution is probably making them part of an object and adding getters, setters that you can send out notifications yourself, as JaredPar showed in his answer

你最好的解决方案可能是让它们成为一个对象的一部分并添加你自己可以发送通知的getter,setter,正如JaredPar在他的回答中所示

#5


0  

You could always have the variables be part of an object and then use a special function to modify the contents of it. or access them via window.

您始终可以将变量作为对象的一部分,然后使用特殊函数来修改它的内容。或通过窗口访问它们。

The following code can be used to fire custom events when values have been changed as long as you use the format changeIndex(myVars, 'variable', 5); as compared to variable = 5;

只要您使用格式changeIndex(myVars,'variable',5),以下代码可用于在更改值时触发自定义事件;与变量= 5相比;

Example:

例:

function changeIndex(obj, prop, value, orgProp) {
    if(typeof prop == 'string') { // Check to see if the prop is a string (first run)
        return changeIndex(obj, prop.split('.'), value, prop);
    } else if (prop.length === 1 && value !== undefined &&
               typeof obj[prop[0]] === typeof value) {
        // Check to see if the value of the passed argument matches the type of the current value
        // Send custom event that the value has changed
        var event = new CustomEvent('valueChanged', {'detail': {
                                                          prop : orgProp,
                                                          oldValue : obj[prop[0]],
                                                          newValue : value
                                                       }
                                                     });
        window.dispatchEvent(event); // Send the custom event to the window
        return obj[prop[0]] = value; // Set the value
    } else if(value === undefined || typeof obj[prop[0]] !== typeof value) {
        return;
    } else {
        // Recurse through the prop to get the correct property to change
        return changeIndex(obj[prop[0]], prop.slice(1), value);
    }
};
window.addEventListener('valueChanged', function(e) {
    console.log("The value has changed for: " + e.detail.prop);
});
var myVars = {};
myVars.trafficLightIsGreen = false;
myVars.someoneIsRunningTheLight = false;
myVars.driverName = "John";

changeIndex(myVars, 'driverName', "Paul"); // The value has changed for: driverName
changeIndex(myVars, 'trafficLightIsGreen', true); // The value has changed for: traggicIsGreen
changeIndex(myVars, 'trafficLightIsGreen', 'false'); // Error. Doesn't set any value

var carname = "Pontiac";
var carNumber = 4;
changeIndex(window, 'carname', "Honda"); // The value has changed for: carname
changeIndex(window, 'carNumber', 4); // The value has changed for: carNumber

If you always wanted to pull from the window object you can modify changeIndex to always set obj to be window.

如果您一直想从窗口对象中拉出,则可以修改changeIndex以始终将obj设置为窗口。

#6


0  

If you were willing to have about a 1 millisecond delay between checks, you could place

如果你愿意在两次检查之间有大约1毫秒的延迟,你可以放置

window.setInterval()

on it, for example this won't crash your browser:

例如,这不会导致浏览器崩溃:

window.setInterval(function() {
    if (trafficLightIsGreen && !someoneIsRunningTheLight) {
        go();
    }
}, 1);

#7


0  

function should_i_go_now() {
    if(trafficLightIsGreen && !someoneIsRunningTheLight) {
        go();
    } else {
        setTimeout(function(){
            should_i_go_now();
        },30);
    }
}
setTimeout(function(){
    should_i_go_now();
},30);