मैं हाल ही में कोणीय और उल्का जैसे जावास्क्रिप्ट ढांचे में देख रहा हूं, और मैं सोच रहा था कि जब कोई वस्तु संपत्ति बदल गई है तो वे कैसे जानते हैं ताकि वे डोम अपडेट कर सकें।वस्तुओं को देखने योग्य बनाने योग्य
मैं थोड़ा आश्चर्यचकित था कि कोणीय ने कुछ प्रकार के गेटर/सेटर को कॉल करने की आवश्यकता के बजाय सादे पुराने जेएस ऑब्जेक्ट्स का उपयोग किया ताकि वह आवश्यक अपडेट कर सके और कर सके। मेरी समझ यह है कि वे नियमित रूप से परिवर्तनों के लिए वस्तुओं को नियमित रूप से मतदान करते हैं।
लेकिन JS 1.8.5 में गेटर्स और सेटर्स के आगमन के साथ, हम उससे बेहतर कर सकते हैं, है ना?
(संपादित करें:: अद्यतन कोड निर्भर-संपत्ति जोड़ने के लिए/विधि समर्थन)
function dependentProperty(callback, deps) {
callback.__dependencies__ = deps;
return callback;
}
var person = {
firstName: 'Ryan',
lastName: 'Gosling',
fullName: dependentProperty(function() {
return person.firstName + ' ' + person.lastName;
}, ['firstName','lastName'])
};
function observable(obj) {
if (!obj.__properties__) Object.defineProperty(obj, '__properties__', {
__proto__: null,
configurable: false,
enumerable: false,
value: {},
writable: false
});
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if(!obj.__properties__[prop]) obj.__properties__[prop] = {
value: null,
dependents: {},
listeners: []
};
if(obj[prop].__dependencies__) {
for(var i=0; i<obj[prop].__dependencies__.length; ++i) {
obj.__properties__[obj[prop].__dependencies__[i]].dependents[prop] = true;
}
delete obj[prop].__dependencies__;
}
obj.__properties__[prop].value = obj[prop];
delete obj[prop];
(function (prop) {
Object.defineProperty(obj, prop, {
get: function() {
return obj.__properties__[prop].value;
},
set: function (newValue) {
var oldValue = obj.__properties__[prop].value;
if(oldValue !== newValue) {
var oldDepValues = {};
for(var dep in obj.__properties__[prop].dependents) {
if(obj.__properties__[prop].dependents.hasOwnProperty(dep)) {
oldDepValues[dep] = obj.__properties__[dep].value();
}
}
obj.__properties__[prop].value = newValue;
for(var i=0; i<obj.__properties__[prop].listeners.length; ++i) {
obj.__properties__[prop].listeners[i](oldValue, newValue);
}
for(dep in obj.__properties__[prop].dependents) {
if(obj.__properties__[prop].dependents.hasOwnProperty(dep)) {
var newDepValue = obj.__properties__[dep].value();
for(i=0; i<obj.__properties__[dep].listeners.length; ++i) {
obj.__properties__[dep].listeners[i](oldDepValues[dep], newDepValue);
}
}
}
}
}
});
})(prop);
}
}
return obj;
}
function listen(obj, prop, callback) {
if(!obj.__properties__) throw 'object is not observable';
obj.__properties__[prop].listeners.push(callback);
}
observable(person);
listen(person, 'fullName', function(oldValue, newValue) {
console.log('Name changed from "'+oldValue+'" to "'+newValue+'"');
});
person.lastName = 'Reynolds';
कौन सा लॉग:
एक छोटे-का-प्रमाण अवधारणा के रूप में, मैं एक साथ इस स्क्रिप्ट को
से बदलनाम "रयान गोसलिंग" से "रायन रेनॉल्ड्स"
एकमात्र समस्या जो मैं देखता हूं वह परिभाषा विधियों जैसे कि fullName()
व्यक्ति वस्तु पर है जो अन्य दो गुणों पर निर्भर करेगी। डेवलपर्स को निर्भरता निर्दिष्ट करने की अनुमति देने के लिए ऑब्जेक्ट पर थोड़ा अतिरिक्त मार्कअप की आवश्यकता होती है।
इसके अलावा, क्या इस दृष्टिकोण के लिए कोई डाउनसाइड्स हैं? जे एस 1.8.5 में getters और setters के
नकारात्मकता यह होगी कि आपको यह लिखना होगा। आप ऐसा क्यों करेंगे जब पुस्तकालय हैं जो आपके लिए करते हैं? –
@AshBurlaczenko: इसे एक सीखने का अभ्यास कहते हैं। – mpen
एक तरफ नोट पर, [नॉकआउटजेएस] (http://knockoutjs.com/) समान रूप से काम करता है, केवल यह जेएस 185 फीचर्स AFAIK का उपयोग नहीं करता है। – Jeroen