I have seen this in a codebase that I am working on that uses es6, but don't fully understand why there are curly brackets. I haven't seen any examples on the web that go into detail on this. Any thoughts, examples?
let aNewElement = new OldElement({theObject: 1})
Because it uses an object (associative array) as parameter in the instance of the class.
Same as:
let param = { theObject: 1 };
let aNewElement = new OldElement(param);
You can pass arguments to the constructor of es6 classes just like regular functions. These can be a simple value like a number, string — but it can also be an object, or even another function. In the example you showed, you are passing an object in using object literal notation: {theObject: 1}. So in the class you might take that object and do something like assign it to a property. For example:
class OldElement{
constructor(someArg) {
// this expects the argument to be an object with a 'theObject' property
// so you can use it any way you want.
console.log(someArg.theObject) // log it
this.obj = someArg.theObject // or save it to a property
}
}
// pass in an object to the constructor
let aNewElement = new OldElement({theObject: "hello"})
// see the property we saved:
console.log(aNewElement.obj)
Related
I am having difficulty in understanding the following code, i have put a comment where i do not understand the concept, what exactly is going on
var ob = {};
var ob2 = ['name'];
for(var op of ob2)
{
ob[op]='at'; // here i dont understand what is happening, why here is an array type brackets
}
console.log(ob);
OUTPUT IS
name:'at'
That is just the syntax for accessing or assigning properties of an object dynamically in javascript.
You can think of it as though you are doing: ob.name = 'at'.
There are two ways to access object properties in JavaScript
var person = {
name: 'Jane'
}
person.name
// or
person['name']
// both return jane
in your case, that iterates through members of the array called ob2
first and only element of that array is a string name and it's given to that object as a prop, which becomes like following
ob['name'] = 'at';
// or
ob.name = 'at';
When to use brackets([]) over dot(.)
If you don't know the prop name at runtime you need to go with brackets, if you do know it you can choose either dot notation or brackets
Basically, it's accessing a property of the object ob. In this case, is accessing and creating new properties.
The loop is getting each index value, and for each assign/create a new property using that index value.
That approach is a dynamically way of creating property-names in an object.
ob['name'] = 'at';
ob.name = 'at'; // Just to illustrate
Read a little the docs here -> JavaScript object basics - Learn web development | MDN
Let's say I have an object myObject with properties a,b,c.
If I want to get rid of property a, I can normally use:
{a, ...rest} = myObject;
And then work with rest, so I can avoid object mutation.
However, I'm dealing with a situation where the name of the property I want to get rid of is abstracted as a string parameter. I can still access said object's property using the brackets syntax, so if:
const stringWithThePropertyName = 'whatever';
then the property would be :
myObject[stringWithThePropertyName]
and that would be equivalent to myObject.whatever
. But what if I want to remove said property from the array?
That is to say, given an object, removing an arbitrary property whose name I take as a string parameter, preferably in an immutable way as I would with the usual spread + destructuring sintax.
You can use bracket syntax while destructuring if you define a variable name to put the found value into:
const myObject = {
foo: 'foo',
bar: 'bar',
baz: 'baz'
};
const stringWithThePropertyName = 'foo';
const { [stringWithThePropertyName]:_ , ...rest } = myObject;
console.log(rest);
(the _ variable will contain the value at foo, so if you just want the object without foo, just don't use the _ variable)
Note that this doesn't actually remove the property from the object - it only creates a new object without that property (which is perfectly fine - avoiding unnecessary mutation is often a good idea). If you actually want to remove the property from the original object, use delete:
delete myObject[stringWithThePropertyName];
I was learning about object literal syntax {}. I learnt that an object can either be created like
var person = {};
person.name = "myName"
or like
var person = {firstname: "myName"}
Now i wanted to pass this object into a function, and so i learnt that objects can also be created on the fly like
sayHelloTo({firstname: "myName"})
Finally, I typed {} in console, and it showed - `Object().
Does this mean than {} is actually a function or something that is actually returning a newly created object, which then gets stored in the variable? Is it a function or something else? Is it same as var person = new Object() ?
The object literal syntax does create a new object but it is not a function. If anything, it's more akin to an operator.
While the spec does have a whole category of literals (11.8), the object literal is not part of that section. Instead, it's defined later under 12.2.6 (object initializer). As the leading note states:
An object initializer is an expression describing the initialization of an Object, written in a form resembling a literal.
(emphasis mine)
I saw following code in a project. can anyone explain what is going on here? What will be value of Attributes? What is happening this[Attributes] = attrs line?
const Attributes = Symbol('User#attrs');
class User {
constructor (attrs) {
this[Attributes] = attrs;
}
}
Symbol creates an un-collidable key for any object:
const first = Symbol('debug-name');
const second = Symbol('debug-name');
first !== second // true;
const anObj = {};
anObj[first] = 123;
anObj[second] = 456;
console.log(anObj) // {Symbol('debug-name'): 123, Symbol('debug-name'): 456}
Note that even though the first and second variables have the same debugging string they create different keys in anObj. Anyone who has access to first can add that key to any object and it will not collide with any other key in that object.
This can be used instead of magic strings to manage protocols:
// ES5
someObject.MY_LIB_attributes = [1, 2, 3];
// Only safe if no other library uses the key
// "MY_LIB_attributes"
// ES2015+
export const Attributes = Symbol('myLib#attributes');
import { Attributes } from 'my-lib';
someObj[Attributes] = [1, 2, 3];
// Safe as long as no other library uses
// *this* Symbol instance for some other purpose.
Edit
Since you've now clarified the question to be only about the line of code this[Attributes] = attrs, see the second part of my answer for discussion of that.
Original Answer
This is a couple of the new ES6 Javascript features.
const Attributes = Symbol('User#attrs'); creates a new Symbol object. The Symbol function and object is described here. It creates a unique identifier object that can then be used for many other uses, one of which is as a property name. There are many other references on the new Symbol feature so I won't repeat all of that here.
The class definition is the ES6 method for declaring prototyped classes. Again, there are many other references on this new syntax so there is no point in repeating all that here. There's an example below of what the equivalent ES5 code is.
This line this[Attributes] = attrs; uses the Symbol generated above to set a property on the newly created object.
The class definition is equivalent to the regular constructor
declaration like this:
function User(attrs) {
this[Attributes] = attrs;
}
Discussion of this[Attributes] = attrs
Attributes is a symbol which can be used as a property name on an object. It's a way of generating a unique key that can be used as a property name. So, this[Attributes] = attrs is setting a property on the newly constructed object and it is using the Attributes symbol as the property name. This Attributes symbol is a unique value that will not match any known string (in fact it won't even match other Symbol objects) so it's a way of making a unique property name.
It is unclear why the code does this:
this[Attributes] = attrs;
instead of just something like this:
this.attrs = attrs;
We would have to see a bit more context for how that is being used and why a plain string property could not also be used in place of the Symbol as you haven't provided enough context for us to know.
One possible use is for privacy. If Attributes is not public, then this is a way of creating a property on the object that the outside world doesn't know how to access because you have to have the current value of Attributes in order to access that properly. As you've shown the code with User and Attributes in the same scope that does not seem like it is private, but perhaps only User is exported to a public scope.
Another possible use is for uniqueness. If the User object may have lots of other properties added to it by other code, then Attributes creates a unique property name that cannot collide with other property names. This seems less likely in this case, but it is one possible use of Symbols.
The question I have deals with an application of adding a new method to the existing String constructor. In Object Oriented Program for Javascript by Stoyan Stefanov, there is an example of using the Array constructor's .reverse() method to create one for the String constructor. Here is the example:
String.prototype.reverse = function() {
return Array.prototype.reverse.apply(this.split('')).join('');
}
I thought the .reverse() method of Array belonged directly to the object of Array. In fact, when I try to do the second bit of code with this statement:,
String.prototype.reverse = function() {
return Array.reverse.apply(this.split('')).join(''); //WITHOUT the .prototype
}
var rev = "karunesh".reverse(); //applying the code here
I get an error in the Firebug Console stating: "TypeError: missing argument 0 when calling function Array.reverse". That does not make any sense to me.
And of course, if I add back in the .prototype, it works perfectly fine.
Also, if is the case that I have to call upon prototype to access the .reverse() method from the Array object, then is it the case that I have to do that for any built-in object in Javascript?
Thanks for the help in advance!
Is it the case that I have to call upon prototype to access the .reverse() method from the Array object
No. To access a method on an object, just access it with dot notation. What you want to do is simply
return this.split('').reverse().join('');
That is just what apply (or call) does:
var arr = this.split('');
return arr.reverse.apply(arr).join('');
and finally arr.reverse === Array.prototype.reverse since that's where Array objects do inherit from. You are not accessing the reverse method on the Array constructor function object itself, you are to access the property that all Array instances share - via their prototype. Yet you hardly will ever need to use the prototype object explicitly, that's only when you're dealing with objects that are not Array instances (do not share the prototype) like arguments objects or NodeLists.
TypeError: missing argument 0 when calling function Array.reverse. That does not make any sense to me.
Array.reverse is a non-standard Array generic method which is only available in Firefox. It's purpose is to simplify the construct of applying Array prototype methods on other objects, and it does take the array-like object as it's first parameter. An example:
Array.reverse([0, 1]) // [1, 0]
which is equivalent to
Array.prototype.reverse.apply([0, 1]);
However, you were doing
Array.reverse.apply([…]/*, undefined*/)
which is calling the Array.reverse function with the array for the (irrelevant) this value and no actual argument, equivalent to
Array.prototype.reverse.apply(undefined)
and that throws the rightful exception.
Array.reverse is undefined (at least in Chrome 29) - Array.prototype.reverse is a function that will reverse the order of the "iterable" it is called on.
The key thing to note here is that Array is not a class like you would have in Java - rather it is a constructor:
[].constructor === Array;
// true
The prototype property of Array is actually what is providing the behavior to any particular instance of Array:
Object.getPrototypeOf([]) === Array.prototype;
// true
// Bad idea, just for an example
var guys = ['Tom', 'Harry', 'Richard'];
Array.prototype.exclaim = function() {
return this.join(", ") + "?!?!?!";
};
guys.exclaim();
// Tom, Harry, Richard?!?!?!
The key here is that JavaScript uses a prototype-based object-oriented pattern, rather than the classical pattern you are more likely familiar with. Instead of having "classes" which contain all the behaviors, but which are distinct from instances, JavaScript has objects, which can be the "prototypes" of other objects, providing data and behavior to the child objects.
// Totally licit OO pattern in JavaScript
var prototypeClass = {
method1: function() { console.log("Hello from method 1!"); },
method2: function() { console.log("Hello from method 2!"); },
classData: 42
};
var prototypeInstance = Object.create(prototypeClass);
prototypeInstance.method1() // Hello from method 1!
prototypeInstance.classData // 42
// And you can modify the class after
// instantiating instances and the changes
// will be picked up by the instances
prototypeClass.happyPrimes = "Don't they teach recreational mathematics anymore?";
prototypeInstance.happyPrimes // The quote from 42