Often, we are presented with an array (IEnumerable) property that specific values need to be extracted. in c# we can do something similar to:
public AssetModel PromoImage {
get
{
return Assets.FirstOrDefault(x => x.AssetTypeCd == "promoimage");
}
private set { }
}
Is there a way to easily to this within Angular 2?
Lodash provides similar functionality to LINQ for JavaScript programs (and then some), though not deferred execution -- LINQ queries are deferred until they are enumerated, while lodash (usually) performs the query immediately and returns an array/object of results. (Though in this case LINQ wouldn't even defer it since FirstOrDefault returns a scalar and not a queryable/enumerable.)
In your case, you would do something like this:
let obj = {
get promoImage() {
return _.find(assets, a => a.assetTypeCd === 'promoimage');
},
// ...
};
Then accessing obj.promoImage will execute the function to obtain the attribute's value.
(Here I assume this is where we are creating the new object, and assets is the assets list in the lexical scope of the constructor function. You can change it to reference this if you are storing data on the object itself and not in constructor upvalues.)
Notes:
Lodash does not depend on Angular at all.
ES6 provides a find() method on the Array prototype, so this feature will be built-in to browsers once ES6 is adopted. Sadly, IE is (as usual) the outlier without any support for it. However, Lodash is still a very useful library to have in your toolkit, and note that Lodash's find() works on objects too, not just arrays.
Related
Consider we have the following JS code:
async function helloAsync(){
return "Hello";
}
function hello(){
return "Hello";
}
In Java, you can load this code into a GraalVM context object using:
context.eval("js", mappingTemplate);
Giving us two members that we can evaluate using:
Value bindings = context.getBindings("js");
final Value executionResult1 = bindings.getMember("hello")
.execute();
final Value executionResult2 = bindings.getMember("helloAsync")
.execute();
As a result, the executionResult2 would be a promise that can be completed within Java. My question is how I can reliably tell that executionResult2 is in fact a promise, and not just a string like executionResult1. Currently, a naive and unreliable approach could be:
if (executionResult.toString().startsWith("Promise") &&
executionResult.hasMember("then") && executionResult.hasMember("catch"))
What are more reliable/elegant ways of recognizing a promise returned from JS?
Can you try to inspect the content via this value.getMetaObject().
The doc say:
Returns the metaobject that is associated with this value or null if
no metaobject is available. The metaobject represents a description of
the object, reveals it's kind and it's features. Some information that
a metaobject might define includes the base object's type, interface,
class, methods, attributes, etc.
Could be useful for your case.
Yes, value.getMetaObject() is the way to go: it returns the JS constructor associated with the value instance, which should be Promise in your case.
I'm reading Eloquent JavaScript's "The Iterator Interface" section and I have trouble understanding why we need to define MatrixIterator function to iterate Matrix's contents. I usually use for inside of another for to iterate the contents of a two-dimensional matrix, similar to this. Is it because the [Symbol.iterator]'s of each object in JS is used whenever you call the shorthand of for loop which is for...of?
Furthermore, am I correct to assume that the standard [Symbol.iterator] cannot automatically iterate a two-dimensional objects and thus, the need to create MatrixIterator and assigning it as:
Matrix.prototype[Symbol.iterator] = function() {
return new MatrixIterator(this);
};
Are we allowed to do this instead: Matrix.prototype[Symbol.iterator] = MatrixIterator;?
Off-topic: I feel like I should know some other things more in-depth as I feel rather confused about these concepts. Could someone also elaborate what interface means? The book did mention it as:
Different pieces of such a program interact with each other through interfaces, limited sets of functions or bindings that provide useful functionality at a more abstract level, hiding their precise implementation.
and
Separating interface from implementation is a great idea. It is usually called encapsulation.
but it did not mention what implementation is.
the shorthand of for loop which is for...of?
No, for … of is not a shorthand for a normal for (…; …; …) loop. It's a completely separate mechanism.
Why do we need to define MatrixIterator function to iterate Matrix's contents?. Is it because the [Symbol.iterator]'s of each object in JS is used whenever you use for...of?
Yes. We define the MatrixIterator as it conforms to the iterator interface, as is expected to be returned by a Symbol.iterator method to be usable in such a loop.
Of course there are alternative ways to achieve this, we don't necessarily need to make an extra MatrixIterator class. A generator function is usually the easiest.
I usually use for inside of another for to iterate the contents of a two-dimensional matrix
Sure, but that's quite some syntactic overhead - two loops, two counters, double indentation. It could be much simpler, and we don't want to repeat this pattern everywhere when we want to iterate a matrix. The iterable interface allows this.
am I correct to assume that the standard [Symbol.iterator] cannot automatically iterate a two-dimensional objects
There is no standard Symbol.iterator method. Every type needs to define it itself. Array.prototype does, for example, but it works only on arrays not on our Matrix class.
Are we allowed to do this instead: Matrix.prototype[Symbol.iterator] = MatrixIterator;?
That doesn't work, as MatrixIterator a) is a constructor that needs to be invoked with new b) takes the matrix instance that it should iterate as an argument
I'm learning how one can achieve OOP patterns in JavaScript. I'd like to know, which one is a correct way to assign a DOM element to a object literal member in pure JavaScript and what are the differences between those examples.
I am doing this so that I could reuse that DOM element in object literal functions and if I change any id, name or class names, I only have to update in one place.
MyObject = {
// Version 1
member: document.getElementByName('elementName'),
// Version 2
member2: function() {
return document.getElementByName('elementName');
},
// Version 3
member3: function() {
document.getElementByName('elementName');
}
};
MyObject2 = {
// Is this member in a different namespace
member: document.getElementByName('element2Name'),
};
// Is this member in a different namespace
member: document.getElementByName('element2Name'),
MyObject2.member and MyObject1.member are different. Javascript doesn't natively support namespace like in other languages but the same can be achieved using the Object literals.
Regarding the 3 different versions for the member assignment, the deciding factor is what kind of access do you need for your variable and how you want to consume that.
// Version 1
member: document.getElementsByName('elementName'),
This assigns the member property the result of the method getElementsByName, The result is a NodeList Collection. To access the property member you need to write it like MyObject.member.
// Version 2
member2: function() {
return document.getElementByName('elementName');
},
The member2 is a function, whereas member wasn't a function and hence how the invocation is done is different. In this case you can get the same result as the version1 by calling MyObject.member2().
// Version 3
member3: function() {
document.getElementByName('elementName');
}
Version 3 doesn't return anything and is useless if you need to consume the result. Basically, this version never stores the result of the function call document.getElementByName('elementName'); and hence the return value is undefined. Like member2, member3 is also a function. But, invoking the function MyObject.member3() returns undefined.
Which version to choose
version 3 is useless as it doesn't return anything.
I do not have enough information of your application to suggest you best match. Based on limited information available, I would prefer version 2 because of the following reasons
Since the value of the result which is defined by document.getElementByName('elementName'); changes and is dependent on DOM. So, i will go ahead with the member2 or version2. i generally prefer function whenever it's not simple and involve some computation. Also, the result of the function call gives the caller information that the result of function call can change. Properties are good when you can define simple data attribute.
Note: A property's value can be a function, in which case the property is known as a method.
This example is from http://eloquentjavascript.net/code/#5.1.
My question is the first bullet-pointed detail; others may be helpful details, but are additional; also see the first short program to see my question in context.
- Why is arrays.reduce() used instead of reduce(arrays()). I know that their's works with the arrays.reduce, but why?
This is an answer to a comment that is useful, but additional to the original question.
My question is with this first program. Since it uses arrays.reduce,
reduce would be a method of arrays, I am not sure why reduce is a
method of arrays. The reason might be in the design decisions of
JavaScript? Thanks, #cookie monster, for that comment!
This is the program with the context of my question-
var arrays = [[1, 2, 3], [4, 5], [6]];
console.log(arrays.reduce(function(flat, current) {
return flat.concat(current);
}, []));
// → [1, 2, 3, 4, 5, 6]
These next details are additional, but may(or may not) be of use:
I know that the [] at the end is used because it is the start parameter in the function reduce so that the other arrays are added to that empty array. I know the .concat is putting together the two arrays like + with strings, but for arrays. Here is what the reduce function, even though it is standard, looks like:
function reduce(array, combine, start){
var current = start;
for(var i = 0; i < array.length; i++)
current = combine(current, array[i]);
return current;
}
One of their other examples showed my way with a single array, if that helps. It looked like:
console.log(reduce([1, 2, 3, 4], function(a, b){
return a + b;
}, 0));
// 10
Thanks! :)
In object oriented design, a guiding principle is that you create or declare objects and those objects have a series of methods on them that operate on that particular type of object. As Javascript is an object oriented language, the built-in functions follow many of the object oriented principles.
.reduce() is a function that operates only on Arrays. It is of no use without an Array to operate on. Thus, in an object oriented design paradigm, it makes complete sense to place the .reduce() function as a method on an Array object.
This object-oriented approach offers the following advantages vs. a global reduce() function:
It is consistent with the object oriented principles used elsewhere in the language.
It is convenient to invoke the .reduce() function on a particular array by using array.reduce() and it is obvious from the syntax which array it is operating on.
All array operations are grouped as methods on the Array object making the API definition more self documenting.
If you attempt to do obj.reduce() (invoke it on a non-array), you will immediately get an runtime error about an undefined .reduce() method.
No additional space is taken in the global scope (e.g. no additional global symbol is defined - lessening the chance for accidental overwrite or conflict with other code).
If you want to know why anyone ever used a global reduce() instead, you would need to understand a little bit about the history of Javascript evolution. Before ES5 (or for users running browsers who hadn't yet implemented ES5 like IE8), Javascript did not have a built-in .reduce() method on the Array object. Yet, some developers who were familiar with this type of useful iteration capability from other languages wanted to to use it in their own Javascript or in their own Javascript framework.
When you want to add some functionality to an existing built-in object like Array in Javascript, you generally have two choices. You can add a method to the prototype (in object-oriented fashion) or you can create a global function that takes the Array as its first argument.
For the Array object in particular, there are some potential issues with adding iterable methods to the Array prototype. This is because if any code does this type of iteration of an array (a bad way to iterate arrays, but nevertheless done by many):
for (var prop in array)
they will end up iterating not only the elements of the array, but also any iterable properties of the array. If a new method is assigned to the prototype with this type of syntax:
Array.prototype.myMethod = function() {}
Then, this new method will end up getting iterated with the for (var prop in array) syntax and it will often cause problems.
So, rather than adding a new method to the prototype, a safer alternative was to just use a global function and avoid this issue.
Starting in ES 5.1, there is a way using Object.defineProperty() to add non-iterable methods to an object or prototype so for newer browsers, it is now possible to add methods to a prototype that are not subject to the problem mentioned above. But, if you wanted to support older browsers (like IE8) and use reduce() type of functionality, you're still stuck with these ancient limitations.
So ... even though a global reduce() is less object oriented and is generally not as desirable in Javascript, some older code went that route for legitimate safety/interoperability reasons. Fortunately, we are putting that road behind us as old version of IE drop off in usage (thank god for Microsoft dropping XP support to finally accelerate the demise of old versions of IE). And newer browsers already contain array.reduce() built in.
JavaScript was/is influenced by the language Scheme, a dialect of Lisp. In Scheme higher order functions are a key component/feature of the language. In fact the reduce function is pretty much equivalent to the fold function in Scheme. In the case of the reduce function in JavaScript, the creators of the language noticed that programmers often need to traverse arrays in a certain fashion, and gave programmers a higher order function where they can pass in a function to specify how they want to manipulate the data. Having higher order functions allows programmers to abstract redundant code therefore creating shorter, cleaner, more readable code.
You can use the reduce function in JavaScript to do many things other than flatten lists. Look here an example.
In Ruby, you can capture a call to a method which is missing and define it on the fly.
What I wanna accomplish in JavaScript is to have an object with no methods. I want a missing method to be translated into a call to emit():
app.isReady() -> app.emit("isReady")
soldier.kills() -> soldier.emit("kills")
I think it's better to capture the missing method error and run emit(methodName) rather than defining all methods (from a fixed list) at runtime. That way we don't have performance overhead if there are hundreds or thousands of events for an object.
What is the best way to do this?
UPDATE: This is an API design so I rather stay out of:
try {
app.isReady()
} catch(e) {
...
}
I want to know how I can accomplish this behind the scenes so the users can use methods as usual.
In that way we don't have a performance overhead if there are hundreds/thousands of events for an object.
I think it's a massive misconception to think the performance overhead of adding methods to an object is smaller then the performance overhead of converting method invocations into emit calls.
However you cannot implement this feature in ES5
One could however implement this using Harmony proxies.
I recommend looking at simulating __noSuchMethod__.
I believe ES6 proxies are experimental and can be turned on in V8 so you could use them with node.js today.
It's not possible to do that consistently at this stage, unless you can guarantee your app will only run on Mozilla, in which case noSuchMethod is what you're after.
As far as I know, none of the other browsers implement this yet.
Use a RegExp test on the function pointer by using the following process:
pass the object literal as an argument
pass the name of the default method as a string
pass the name of the fallback method as a string
using subscript notation to dereference the function pointer
use a regexp to check the type against the name function
if it succeeds, call the default using subscript notation
if it fails, call the fallback using subscript notation
For example:
/* Define mapping */
var app = {"emit": emit};
/* Define interface */
function emit(){}
function \u1000missing(object, method, fallback)
{
/* Existence check */
if (/function/.test(object[method]) )
{
object[method]();
}
/* reify */
else
{
object[fallback](method)
}
}
\u1000missing(app,"isReady","emit")
You might ask why you'd ever want to use subscript notation. Subscript notation allows for dynamic creation of properties and methods. So if you ever do any sort of metaprogramming, you'll most likely be using the subscript notation.
References
Are there equivalents to Ruby's method_missing in other languages?
JSPerf: Method Missing
Handling a call to a missing method in different languages
jQuery is a Monad
Message forwarding in Smalltalk
Performance from Aligning Smalltalk and JavaScript Classes
Can Perl be Smalltalk?
How learning Smalltalk can make you a better developer
Reflective Facilities in Smalltalk-80
12.1. QMetaObject - The Meta Object Pattern
Object Programming and Object-Oriented Programming
Things you should know about JavaScript
Respond to an Unknown Method Call
Creating Thread-Safe Components With OnMissingMethod()
On the design of the ECMAScript Reflection API (pdf)
Does Not Understand
I've create a Node.js package to deal with your situation. It's called auto-object.
Here's a glance:
const myObject = autoObject.createObject(function(name) {
if(name.startsWith("say")) {
return function() {
return name.substr(3);
}
}
return name;
});
myObject.foo; ///< "foo"
myObject.sayFoo(); ///< "Foo"
myObject.sayBar(); ///< "Bar"
What's more, this works with class too.