I'm not a guru at JS. Today I was told during a code review that for the following code below, Reference type values need to be initialized in the constructor which means change this somehow referring to the constraints: {}
define(["dojo/_base/declare",
"dijit/form/CurrencyTextBox",
"xxxx/util/currencyUtil",
"./_InputWidgetMixin",
"../secure/_SecureWidgetMixin"
],
function (declare, xxxTextBox, xxxUtil, _InputWidgetMixin, _SecureWidgetMixin) {
return declare("xxx.widget.input.xxxTextBox", [xxxTextBox, _InputWidgetMixin, _SecureWidgetMixin], {
constraints: {},
reset: function () {
this._set("value", this.resetValue);
},
not sure what this means and why I need to move this and if it's a Dojo thing or plain JS thing to worry about and why.
I would say this is a dojo thing, it's to do with how dojo implements a class-like system. To understand why this is important, take a look at this recent question : Dojo instances of same widgets are not saparated.
As mentioned there, arrays and objects are shared across instances, so if you don't want this behaviour, you should initialize them in your constructor. Dojo docs on declare
Your constraints will be a shared object across all instances of xxxTextBox unless in your constructor you assign a new object to constraints:
this.constraints = {};
This is because the constraints value is part of a prototype object and therefore this is a javascript thing. Once you assign this.constraints you obscure the reference to the shared constraints with the objects own local copy.
Related
In my journey to become stronger in JavaScript, I have taken up a challenge to add a method, myMethod(), to the JavaScript Object class that can be called on a given Object, myObject, in order to manipulate its contents.
I have gotten as far as adding myMethod() to the Object prototype and traversing through myObject via myObject.myMethod(); however, I'm running into a curious problem: at the end of the given object, myMethod() is printed as an value of myObject even though, to my knowledge, it should not be.
Object.prototype.myMethod = function()
{
for (var key in this)
{
console.log(this[key]);
}
}
function processData(input)
{
//Enter your code here
var myObject = JSON.parse("{ \"myParam\": \"myValue\", \"anotherParam\": 123 }");
myObject.myMethod();
}
The following is the output of this code:
myValue
123
[Function]
Changing myObject[key] to myObject[key].toString() has the following output:
myValue
123
function ()
{
for (var key in this)
{
console.log(this[key].toString());
}
}
I am executing this script in WebStorm using a Node.js runtime.
The requirements of this challenge only calls for the contents of myObject, and I can't figure out how to stop myMethod() from showing up here. Is there something I'm missing?
In my journey to become stronger in JavaScript, I have taken up a challenge to add a method, myMethod(), to the JavaScript Object class that can be called on a given Object, myObject, in order to manipulate its contents.
Beware that this practice is seriously frowned-upon (here in 2017, possibly more than it strictly necessary*). Extending any built-in prototype is a bit fraught, but extending Object.prototype is particularly problematic since, of course, almost all objects inherit from it.
But if you're going to extend a prototype, it's important to add a non-enumerable property via Object.defineProperty or similar:
Object.defineProperty(Object.prototype, "myMethod", {
value: function() { /* ... */ }
});
The default for enumerable is false, so it won't show up in for-in loops, Object.keys arrays, etc.
* The "don't extend built-in prototypes" mantra started before ES5's introduction of a way of defining non-enumerable properties (e.g., defineProperty). Now that we can define non-enumerable properties, the chief concern is inter-script conflict, each trying to use the same name for something, or conflict with new features as they're added to JavaScript.
Use Object.defineProperty().
The Object class is used in a lot of libraries and frameworks and therefore is best left alone, but can be useful for things such as poly-fills for browser compatability.
if (!Object.prototype.myMethod) {
Object.defineProperty(Object.prototype, 'myMethod', {
value: function() { /* customer code here */ }
})
}
I want to turn a plain JavaScript object into one with a prototype etc, without cloning the object. Is this possible?
Essentially, instead of this:
var MyClass = function(fromObj) {
this.propA = fromObj.propA;
this.propB = fromObj.propB;
...
}
inherit (SuperClass, MyClass);
I would like to:
var MyClass = function(fromObj) {
this = fromObj;
}
inherit (SuperClass, MyClass);
To be extra clear: I would like the object returned from the constructor to be the same object that was passed in (not a duplicate, not a clone).
Is there a way to achieve this? Or a better way to describe what I'm asking for? :)
I'd like this for two reasons:
We're loading a lot of objects, and speed and memory may start to matter.
There are lots of places where the "plain old javascript objects" are used, and it may be hard to make sure they all point to the new instantiated object.
I guess you want to do this so that the objects created by JSON.parse are instances of something other than Object.
One option is to assign a new [[Prototype]] that is from the specified constructor using Object.setPrototypeOf, however there are performance warnings for this on MDN (I have no idea on the validity of the claims).
A more efficient solution might be to create "wrapper" objects and attach those created by JSON as a property. This approach is used by a number of DOM libraries and avoids the possibility of property names from the JSON data clashing with method names of the object (e.g. the DOM libraries can use methods with the same name and characteristics as DOM methods, but don't overwrite or clash with them).
Data could be held in a closure so that only getters and setters defined by the constructor can access it.
When you use require and loads a module, you seems capable of create a function with properties or a object that can be invoked as a function.
console.log(require('events').EventEmitter);
//{ [Function: EventEmitter] defaultMaxListeners: 10, listenerCount: [Function] }
I have done this before* using the require module so I can replicate it. But I want to create more manually. I have some questions in this regards:
Is possible replicate this manually, harcoded without require?
Is possible to create any type of property like getters or setters?
Is posible to create one of these 'objects' when you use a constructor?
Thanks in advance.
*Or I remember that, I have a terrible memory
Edited:
To be clear: I'm not talking about prototype. In my example you can see that, for example, defaultMaxListeners dont come from prototype. In code:
EventEmitter.defaultMaxListeners // 10
EventEmitter.prototype.defaultMaxListeners // undefined
EventEmitter() //No error
Is possible replicate this manually, harcoded without require? Is
possible to create any type of property like getters or setters? Is
posible to create one of these 'objects' when you use a constructor?
Yes
In JS, functions are also objects. You can attach properties to them like any other object. Also, in JS, functions can be used as both functions as well as object constructors.
The following example shows what you can do to a function. I'm using Classical OOP terms, since I don't know what they call them in JS.
function SomeConstructor(){
this.instanceProperty = 'foo';
}
// Instance Method
SomeConstructor.prototype.method = function(){
console.log('method');
}
// Static Method
SomeConstructor.staticMethod = function(){
console.log('static');
}
var test = new SomeConstructor();
test.method();
SomeConstructor.staticMethod();
I've run into a javascript question that I don't know how to resolve. I'm grouping a bunch of variables and methods into a DocManager object. Everything related to managing "documents" in my application lives here. Basically, the DocManager acts like a class with a single instance.
Ex:
var DocManager = {
doc_list : [], //Array of documents containing content and metadata
doc_index : 0, //Index of the currently visible document
loadDocList : function( collection_id, csrf_token, seq_list ){
...
},
showDocument : function(seq_index){
...,
},
...
};
Now I've run into a situation where I'd like to subclass DocManager for use on different pages with different controls. I need to add some methods and overwrite others. Most of the functionality the object will stay the same.
What's the easiest way to do this? I know javascript has a class/prototyping syntax for full-fledged object-orientation, and others have built OOP frameworks for js, but that seems like overkill for this situation. I'd prefer to not learn a lot of new syntax to carry out this simple kind of object orientation. What would you recommend?
You can simply overwrite the functions you have assigned to it.
YourDocuManager.showDocument = function(index, newindex, whatever) {
....
}
from that moment it'll use the new function assigned.
Currently I'm trying to use John Resigs Simple Javascript Inheritence library, this works great but when I try to modify default member variables, it seems to influence the prototype rather than only the instance:
http://jsfiddle.net/u2MWL/1/
As you can see, the events is of different length each time you create a new instance. Am I using the library in the wrong way or is this a known flaw? What are the alternatives?
The problem here is that you are extending the class with events: []
Array (and {} object) variables are references. So by extending the class with an array, every instance of the class is going to have an events equal to the same referenced array.
To get around this you could do
var Test = Class.extend({
events: null,
init: function() {
this.events = [];
this.events.push(1);
alert(this.events.length);
},
say: function(words) {
}
});
This way, each time a class is initialized a new array (thus reference) is appointed to events. Not elegant, I know, but it should work.