I read a few books about JavaScript, and it is a very powerful language for building web applications using OOP, but now I have a problem that I don't know if it can be solved:
var myObj = {};
myObj.properties = {};
myObj.properties.myProperty = 'foo';
Let me explain, now I have myObj .. setted the properties object inside... now, if I ask
for myObj.properties.myProperty I will get foo. But what if I ask for myObj.properties.notSettedValue ? (that is undefined)
I read about Object.defineProperty on MDN that can set a setter and a getter on a property.
I tried to set the "get" value on myObj.properties
Object.defineProperty(myObj, 'properties', {
get : function(){
console.log("called custom get property.", this, arguments);
}
});
... but nothing to do, the get function declared for myObj.properties work only for itself. The custom function is called only when I request myObj.properties. Not for its children.
There's a solution to pass the requested myObj.properties.notSettedValue to a get function of myObj.properties?
(without using a function or a method like myObj.properties.getItem('notSettedValue'))
Basically what you're asking is whether it's possible to set up a function that gets called if code tries to retrieve a property from an object that doesn't exist on that object.
No, JavaScript doesn't have that ability. ES6's proxies will make something quite similar possible, but as of ES5, there is no "catch all" getter feature.
Your only ES5-compatible mechanism for doing that kind of catch-all is as you've said, using a function rather than a property (your getItem).
Object in JavaScript are dynamic. You can add new properties on the fly, like you did in you example e.g. myObj.properties = {}
What happens under the hood is that the interpreter will try to find a property called properties on the myObj instance; If there is no such property then it will navigate through the prototype chain. In this example it will visit the prototype of the Object constructor, as myObj is an object literal. If it cannot find that property in the prototype chain then it will create it and add it as a new member of the object.
The same applies when you want to read a property. But in this case it will return undefined if it can't find the requested property; So unless you explicitly define the property, it will always return undefined. This applies both for when you access a simple property and a ES5 property.
Related
I have this function here, I need to work with this other function called OrderRepository in another file.
main.js
function main() {
var orderRepo = new OrderRepository();
// Your code here
}
orderrepository.js
function OrderRepository() {
}
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
These were given as examples to use, 1 question rolled into 2 parts:
1) var orderRepo = new OrderRepository();
Can you initialize a function like this?
2) In the orderrepository.js:
function OrderRepository() {
}
is being called in main.js, but nothings inside of it, this was given as-is in the assignment, is this just a typo and really they meant to throw everything inside that function or am I missing something?
Shouldn't it look like this?
Expected
function OrderRepository() {
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
}
Diving deeper into JavaScript, the language is hard to understand. JavaScript is not really OOP (imho), at least it does not implement the common OOP concept. Some call it object-based language. There are no classes. Recent ECMA Script standards do implement the class keyword, however, it is syntax sugar. Used with the new keyword it builds the same objects as you can achieve by 'constructor' functions.
Everything in JavaScript is an object, even numbers and functions. Every function can act as constructor function. The new keyword call a constructor function with a newly creates empty object as the function's this context. The function can do what it wants. If it does not return anything, its this context is returned by the new expression.
Since there are no classes, there is no inheritance. Some inheritance-like behavior is achieved by the prototype concept. In most cases the constructor will return nothing and sometimes modify the this object by adding properties. Methods are properties holding a function object. The object in the new context of a constructor call will have a prototype object reference as the __proto__ property. This is copied by the new operator from the prototype property of the called constructor function. The default is an empty object.
// empty constructor function
function OrderRepository() {
}
// define a function property on the constructor's prototype object
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [ /* array of objects */ ],
return yesterdaysOrders;
};
// create an empty object with a `__proto__` property holding a
// reference to the object { getYesterdaysOrders: function(){/*code*/} }
var obj = new OrderRepository();
Now, when the method invocation obj.getYesterdaysOrders() is tried, JavaScript will look if there is such a property defined in obj. If not, it looks if there is a reference in obj.__proto__ and the property name is searched the properties of obj.__proto__. If not, the same step is repeated until it was found or the __proto__ property in the chain is null. Since obj.__proto__.getYesterdaysOrders is defined, it is checked if it is a callable function object and finally invoked with a this context of obj since we called obj.getYesterdaysOrders(). Otherwise an error is thrown.
NOTE: Even if the major browsers do expose the __proto__ property, it is not part of the standards. Do not use it directly (except for debugging at development time) and even more important: do not manipulate it. If you really need to get or manipulate a prototype (__proto__) of an object instance after construction, use the methods of the builtin Object object.
Upon your last edit: Your expected code would define a new function object in prototype on each instantiation (and thus constructor invocation). This is not what you want, it's just needless overhead.
Regarding the first part, it looks like this assignment is dealing with how to create instances of objects in JavaScript as that is what the new operator does.
You can find more information regarding new on the MDN.
Regarding the second question, it is dealing with how to create objects that inherit methods. So, yes it is empty, until you get to the prototype expression.
The expected code would not give you the inheritance in this case. Notice how OrderRepository is repeated inside the function, which would be invalid. Javascript requires you to add inheritance to the special prototype property. Code that is added to the function declaration, would be scoped to the function only in that case.
You can find more information about prototype on the MDN.
I saw a blank stub on MDN a while ago for the Reflect object in javascript but I can't for the life of me find anything on Google. Today I found this http://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect-object and it sounds similar to the Proxy object apart from the realm and loader functionality.
Basically, I don't know whether this page I found only explains how to implement Reflect or if I just can't understand its wording. Could someone please explain to me generally what the methods of Reflect do?
For instance, on the page I found says that calling Reflect.apply ( target, thisArgument, argumentsList )
will "Return the result of calling the [[Call]] internal method of target with arguments thisArgument and args." but how is that any different than just calling target.apply(thisArgument, argumentsList)?
Update:
Thanks to #Blue, I found this page on the wiki
http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api&s=reflect
which to the best of my knowledge says that the reflect object provides method versions of all the actions that can be trapped by proxies to make forwarding easier. But that seems a little weird to me since I don't see how it's entirely necessary. But it Seems to do a little more than that, particularly the par that says double-lifting but that points to the old proxy spec/
UPDATE 2015:
As pointed out by 7th's answer, now that ES6 (ECMAScript 2015) has been finalized, more appropriate documentation is now available:
ES6 spec, Reflection
MDN Reflect (including details and examples to all of its methods)
**Original answer (for (historic) understanding and extra examples)**:
The Reflection proposal seems to have progressed to the Draft ECMAScript 6 Specification. This document currently outlines the Reflect-object's methods and only states the following about the Reflect-object itself:
The Reflect object is a single ordinary object.
The value of the [[Prototype]] internal slot of the Reflect object is the standard built-in Object prototype object (19.1.3).
The Reflect object is not a function object. It does not have a [[Construct]] internal method; it is not possible to use the Reflect object as a constructor with the new operator. The Reflect object also does not have a [[Call]] internal method; it is not possible to invoke the Reflect object as a function.
However, there is a short explanation about it's purpose in ES Harmony:
The “#reflect” module serves multiple purposes:
Now that we have modules, a “#reflect” module is a more natural place for many of the reflection methods previously defined on Object.
For backwards-compatibility purposes, it is unlikely that the static methods on Object will disappear. However, new methods should likely be added to the “#reflect” module rather than to the Object constructor.
A natural home for proxies, avoiding the need for a global Proxy binding.
Most methods in this module map one-to-one onto Proxy traps. Proxy handlers need these methods to conveniently forward operations, as shown below.
So, the Reflect object provides a number of utility functions, many of which appear to overlap with ES5 methods defined on the global Object.
However, that doesn't really explain what existing problems this intends to solve or what functionality is added. I suspected this could be shimmed and indeed, the above harmony-spec links to a 'non-normative, approximate implementation of these methods'.
Examining that code could give (further) idea's about it's use, but thankfully there is also a wiki that outlines a number of reasons why the Reflect object is useful:
(I've copied (and formatted) the following text for future reference from that source as they are the only examples I could find. Besides that, they make sense, already have a good explanation and touch the question's apply example.)
More useful return values
Many operations in Reflect are similar to ES5 operations defined on Object, such as Reflect.getOwnPropertyDescriptor and Reflect.defineProperty. However, whereas Object.defineProperty(obj, name, desc) will either return obj when the property was successfully defined, or throw a TypeError otherwise, Reflect.defineProperty(obj, name, desc) is specced to simply return a boolean that indicates whether or not the property was successfully defined. This allows you to refactor this code:
try {
Object.defineProperty(obj, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
To this:
if (Reflect.defineProperty(obj, name, desc)) {
// success
} else {
// failure
}
Other methods that return such a boolean success status are Reflect.set (to update a property), Reflect.deleteProperty (to delete a property), Reflect.preventExtensions (to make an object non-extensible) and Reflect.setPrototypeOf (to update an object's prototype link).
First-class operations
In ES5, the way to detect whether an object obj defines or inherits a certain property name is to write (name in obj). Similarly, to delete a property, one uses delete obj[name]. While dedicated syntax is nice and short, it also means you must explicitly wrap these operations in functions when you want to pass the operation around as a first-class value.
With Reflect, these operations are readily defined as first-class functions:
Reflect.has(obj, name) is the functional equivalent of (name in obj) and Reflect.deleteProperty(obj, name) is a function that does the same as delete obj[name].
More reliable function application
In ES5, when one wants to call a function f with a variable number of arguments packed as an array args and binding the this value to obj, one can write:
f.apply(obj, args)
However, f could be an object that intentionally or unintentionally defines its own apply method. When you really want to make sure that the built-in apply function is called, one typically writes:
Function.prototype.apply.call(f, obj, args)
Not only is this verbose, it quickly becomes hard to understand. With Reflect, you can now make a reliable function call in a shorter and easier to understand way:
Reflect.apply(f, obj, args)
Variable-argument constructors
Imagine you want to call a constructor function with a variable number of arguments. In ES6, thanks to the new spread syntax, it will be possible to write code like:
var obj = new F(...args)
In ES5, this is harder to write, because one can only use F.apply or F.call to call a function with a variable number of arguments, but there is no F.construct function to new the function with a variable number of arguments. With Reflect, one can now write, in ES5:
var obj = Reflect.construct(F, args)
Default forwarding behavior for Proxy traps
When using Proxy objects to wrap existing objects, it is very common to intercept an operation, do something, and then to "do the default thing", which is typically to apply the intercepted operation to the wrapped object. For example, say I want to simply log all property accesses to an object obj:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
// now do the default thing
}
});
The Reflect and Proxy APIs were designed in tandem, such that for each Proxy trap, there exists a corresponding method on Reflect that "does the default thing". Hence, whenever you find yourself wanting to "do the default" thing inside a Proxy handler, the correct thing to do is to always call the corresponding method in the Reflect object:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
The return type of the Reflect methods is guaranteed to be compatible with the return type of the Proxy traps.
Control the this-binding of accessors
In ES5 it's fairly easy to do a generic property access or property update. For instance:
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update
The Reflect.get and Reflect.set methods allow you to do the same thing, but additionally accept as a last optional argument a receiver parameter that allows you to explicitly set the this-binding when the property that you get/set is an accessor:
var name = ... // get property name as a string
Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`
Reflect.set(obj, name, value, wrapper)
This is occasionally useful when you're wrapping obj and you want any self-sends within the accessor to get re-routed to your wrapper, e.g. if obj is defined as:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
Calling Reflect.get(obj, "foo", wrapper) will cause the this.bar() call to get rerouted to wrapper.
Avoid legacy __proto__
On some browsers, __proto__ is defined as a special property that gives access to an object's prototype. ES5 standardized a new method Object.getPrototypeOf(obj) to query the prototype. Reflect.getPrototypeOf(obj) does exactly the same, except that Reflect also defines a corresponding Reflect.setPrototypeOf(obj, newProto) to set the object's prototype. This is the new ES6-compliant way of updating an object's prototype.
Note that: setPrototypeOf also exists on Object (as correctly pointed out by Knu's comment)!
EDIT:
Side-note (addressing comments to the Q): There is a short and simple answer on 'Q: ES6 Modules vs. HTML Imports' that explains Realms and Loader objects.
Another explanation is offered by this link:
A realm object abstracts the notion of a distinct global environment,
with its own global object, copy of the standard library, and
"intrinsics" (standard objects that are not bound to global variables,
like the initial value of Object.prototype).
Extensible web: This is the dynamic equivalent of a same-origin
<iframe> without DOM.
Worth mentioning though: all this is still in draft, this is not a specification etched in stone! It's ES6, so keep browser-compatibility in mind!
Going by the draft document found on the wiki,
http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts
We get the line about "single ordinary object" which it clarifies in the draft. It also has the function definitions.
The wiki should be reliable since you can find a link to it from the emcascript website
http://www.ecmascript.org/dev.php
I found the first link by google though and didn't have any luck finding it by searching the wiki directly.
In the code below I am trying to understand the behavior of the method assigned to the prototype object and those defined at the object definition of the function Vehicle:
function Vehicle(theMake) {
var make = theMake;
//this. attachs "make" to this instance of
//the object Vehicle which is infact an object of type Object
this.getInfo = function () {
return 'Local definition of getInfo, Vehicle: ' + make;
};
}
Vehicle.prototype.getInfo = function () {
//prototype will not have access to the variable make
return 'Overriding getInfo for all instances of Vehicle';// which later I realized is just the opposite( check the selected answer)
}
var car1 = new Vehicle('Honda');
alert(car1.getInfo());//Displays: Local definition of getInfo, Vehicle: Honda
1- Despite providing the definition of Vahicle.prototype.getInfo(), why the car1.getInfo() will be invoked? ( the local copy not the generic one?) why it ie being ignored?
If i remove the "this.getInfo = function()..."
then the generic getInfo will be invoked by car1.getInfo()
2-How can I invoke the car1.prototype.getInfo())? If I call it like car1.prototype.getInfo().call
the interpreter says: Unable to get property 'getInfo' of undefined or null reference
You should be assigning getInfo in only one place. Either in the prototype or in the constructor (preferably prototype), but NOT both places.
If you do both, the one assigned in the constructor will take precedence because it is assigned to the actual object which is searched first (before the prototype is searched). The prototype is only used if there is no property with the desired name already attached directly to the object. Because you've assigned a .getInfo property directly to the object in the constructor, the prototype is not searched when resolving that property name (because it's already found).
Since your code indicates that you think the .prototype version is the override, it appears that you just have that logic backwards. The getInfo() assigned to the object in the constructor is what overrides the prototype.
If you truly wanted to execute the prototype version, you could access it directly on the prototype:
Vehicle.prototope.getInfo.call(car1);
But, really if you want access to both methods, you should just given them different names so they are both accessible as car1.method1() and car1.method2().
So to summarize from your specific questions:
1- Despite providing the definition of Vahicle.prototype.getInfo(),
why the car1.getInfo() will be invoked? ( the local copy not the
generic one?) why it ie being ignored?
The object itself is searched before the prototype so the getInfo assigned directly to the object in the constructor will be found by the interpreter first and the prototype will not be searched.
2-How can I invoke the car1.prototype.getInfo())? If I call it like
car1.prototype.getInfo().call the interpreter says: Unable to get
property 'getInfo' of undefined or null reference
The best solution is to give the two functions different names so they are both callable in the conventional way. If you absolutely have to call the prototype version, you can do so as Vehicle.prototope.getInfo.call(car1);.
One might ask, why are you giving these two functions the same property name? That's what is creating the problem in the first place.
The prototype chain allows the object to delegate to it's prototype when there is a failed lookup on the constructor. You have provided an instance where there will not be a failed lookup, so there is no need for it to look up the method on the prototype.
I want to create an object just using the Object.create function (without any prototype, first argument as null).
I read somewhere that properties determine the state of an object in JavaScript and JavaScript has three different kinds of properties:
named data properties
named accessor properties
internal properties
So when I define a function in an object, should I always define it as a named accessor property:
var obj = Object.create(null, {
a:{
get:function(){
alert('jQuery nyan!');
}
}
});
Or should I just define the function as a named data property when it is neither a setter nor a getter? [e.g some jQuery functions that makes changes to the DOM obj]
var obj = Object.create(null, {
a:{
value:function(){
alert('jQuery nyan!');
}
}
});
Which approach should I take? In terms of performance (speed) and memory management do they have differences? They both appear to work without any exception.
obj.a;
//output: 'jQuery nyan!'
To make it easier to refer to them, let's define them as follows
var objA = Object.create(null, {a: {get: function(){alert('jQuery nyan!');}}});
var objB = Object.create(null, {a: {value:function(){alert('jQuery nyan!');}}});
Now, there is almost no difference between the invocation of objA.a vs objB.a(), except the use of ().
There are some differences, however.
The main difference is that you can't pass parameters to a getter, it is invoked as-is. This means objA.a(1,2,3) will not invoke the function with arugments 1, 2, 3. It will in fact throw an error after invoking, assuming the getter does not return a Function (you're effectively trying to do undefined(1,2,3)).
A second difference requires us to remember Object.create's second parameter takes an object of descriptors, which includes the flag writable (which defaults to false). The difference here is you can not set writable:true on objA.a because "A property cannot both have accessors and be writable or have a value". This means that if you want the method of the getter changed, you must re-define the property, whereas for value you could enable the use of = to change the method associated with the property.
Additionally, with no setter objA.a = <expr> will not perform any action at all.
Normally, you'd only use getters and setters in the following instances, with value as the standard behaviour otherwise;
Lightweight calculating an output
Validating input (to protect an object)
Hiding a variable from direct access
Keeping a standard API where variable or property names may change
If you don't care about compatibility, using getter and setters could be a good approach to replace setNAME()s and getNAME()s. And there is no significant performance gain/loss comparing to function version.
Note that, cause it looks like accessing an variable, instead of calling a function, so the getter/setter function should be very light weight to meet this expectation.
And don't ever use one function for both getter and setter like jQuery does, it's simply very slow. As there is no function signature in javascript, simulate it with if/else will cause lots of performance loss.
EDITED
What is the difference in doing:
var a = function(){};
a.myProperty = function(){};
Versus:
var a = function(){};
a.prototype.myProperty = function(){};
I realise this might be a silly or vague question but what do I need to understand to know the difference between the two and when to use one over the other?
Note that the question has been heavily edited since it was first posed, which is why the existing comment and answer make no sense.
All functions have prototypes. The methods attached to these prototypes are available to instances of objects created by calling the function as a constructor. So in the second example, if you write var o = new a(); then you will be able to invoke o.myProperty();.
Additionally all functions are objects, so you can set arbitrary properties directly on the function itself, as per the first example. You can also access the function from the object using o.constructor (or this.constructor from a member function). This could be used to implement the equivalent of C++ static class variables.
There is no difference. Your setting a property on an object.
Note that your second example fails because you havn't set a.prototype to a value.
Of course if you made a a function then it gets a prototype property by default.
And that .prototype property has a special property. If you invoke new someFunction then the [[Prototype]] of the return value is someFunction.prototype.
This only applies if .prototype is a property of a function. Since new only works on functions.