I have two objects:
object1={
type: 'obj1',
nName: 'nName'
}
object2={
type: 'obj2',
pName: 'pName'
}
In my js code, I have:
object=GET_OBJECT();
The GET_OBJECT() method returns either object1 or object2, then, I would like to access the object's name attribute which is either nName or pName.
I have one method which will get the name (pName or nName) of the returned object:
function getName(Object, name){
return object.name;
}
where I would like the name to be a variable, so that I can access the pName or nName in this way:
object=GET_OBJECT();
var name='';
if(object.type=='obj1')
name='nName';
else
name='pName';
var finalName=getName(object, name);
But seems it won't work since in:
function getName(Object, name){
return object.name;
}
name is a variable. In JS, is there any way to access attribute as a variable?
Try like this:
function getName(Object, name) {
return Object[name];
}
AS many times before I wonder why people provide solutions and not knowledge. Otherwise the asker will repeat the same mistakes over and over.
The original code uses a function to retrieve an attribute. It is assumed that it is possible to use the parameter to invoke the parameter. In more technical words, Dot notation is being used which must be a valid JavaScript identifier. Tha name after the dot is the pointer the content. Therefore getName always is accessing the attribute name which is likely to be undefined.
The solution shown uses Bracket notation in which uses the content of the parameter (which may not exist) as identifier and then, it resolves the content and this is why it actually works.
Dot notation is faster and easier to read and would be adviced if both are valid options. Bracket notation is to be used when you need resolving in run time. That is what happens when you define setters and getters internally. The following code will use the string passed to ensure (using bracket notation) that whenever you use the identifier by dot notation will call the functions passed.
function myClass(){
//setX and getX should be also defined previous to this
this.__defineSetter__("x",this.setX);
this.__defineGetter__("x",this.getX);
//Object.defineProperty can also be used
};
var tObject = new myClass();
tObject.x = 10; //Getter being called
Related
Can someone explain to me the difference of when to use a function by feeding your variables into the parenthesis, and when to tack the function on after the variable with a period, like using the toString() function?
example code
function addMe(a){
a = a+1;
return a;
}
var num = 1;
addMe(num);
num.toString();
I'm not actually sure if my syntax is correct, but I want to know when to feed a variable as a parameter, like how I feed the variable num, to the addMe function. And when to use the function .toString() by putting a period after the variable and typing out the function.
could I have done something like this- provided I built my function correctly?
var num = 1;
num.addMe();
Thanks for the help!
The first is used for simple 'stand alone' functions, while the latter is used for object methods. E.g a number object by default has a toString() method. Some object methods may also require parameters to be passed between the parentheses.
Variables (a function declaration is just a function stored in a variable) are looked up in the scope chain (going up to the next outer scope until a variable with the name is found):
let a = 1; // outer scope
{ // inner scope
console.log(a); // looked up in "inner scope", than "outer scope"
}
Properties of an object are looked up in the objects prototype chain, so if you do
a.b
then a gets looked up in the scopes as explained above, then b is accessed on the resulting object (everything is an object in JavaScript, except for "nothing" (undefined, null)) by looking up the prototype chain. For a simple object, the chain is quite short:
const a = { b: 1 }; // object -> Object.prototype
Here b will be found in the object itself. However all objects inherit from the Object.prototype object, so if you add a property to that (please don't):
Object.prototype.test = 1;
you can then look it up on every object, as the lookup traverses up the prototype chain, and reaches Object.prototype:
console.log({}.test); // 1
Now for numbers (like in your case), they inherit the Number.prototype so you could do:
Number.prototype.addMe = function() {
console.log(this);
};
// two dots are needed to distinguish it from numbers with a fraction (e.g. 1.2)
1..addMe();
That said, now addMe can be called on every number, everywhere in your code. While that might seems useful, it is actually a pain as you don't know where a certain method was added
1..whereDoIComeFrom()
that makes code unreadable and unstructured. Instead if you need a certain functionality multiple times, abstract it into a function, don't touch the native prototypes.
I assume that addMe is just a simplified example, if it isn't, read on:
If you pass an argument to a function in JavaScript, the value will be copied (it is a bit more complicated with non primitives (everything except numbers, booleans etc.)) into the parameter variable of the function called so here:
function addMe(a){
a = a+1;
console.log(a); // 2
return a;
}
var num = 1;
addMe(num);
console.log(num); // 1 ... ?
you actually got two variables (a and num), changing a does not change num. But as you return a you can do:
num = addMe(num);
which copies the value of num into a, then increases a by one and then copues the value of a back to num.
When you did var num = 1 you created a JavaScript object. It looks just like a number but you can think of everything in JavaScript as an object (simplification) and all these objects have different features. So a number has some features, a string has some other features, etc.
You mentioned one feature: toString. Another feature would be toLowerCase.
toString and toLowerCase are functions that come with JavaScript. These functions are then "put on" all of these objects for us to use.
I can have a string variable like
var text = 'MY TEXT'
var lowercaseText = text.toLowerCase()
console.log(lowercaseText) // my text
This code will work because it was decided that the toLowerCase function should work on strings
I can also have an array (list of items)
const list = ['A', 'B', 'C']
const answer = list.toLowerCase()
console.log(answer)
But this code won't work because toLowerCase doesn't work on arrays. So you get the following error message: list.toLowerCase is not a function.
Basically its saying: I don't know what toLowerCase means when used on this list variable (array).
In JavaScript this is called prototypes. Prototype is a way for JavaScript to get some feature from another. Basically: I have all kinds of functions, what object can use what functions. This is called the prototype chain.
In both cases you are using a function. addMe is a function you created and toString is a function in JavaScript that has been placed on objects through this prototype-chain.
Im not actually sure if my syntax is correct
Yes your syntax is correct. Your addMe function is the standard way to create a function in JavaScript.
But i want to know when to feed a variable as a parameter, like how i
feed the variable num, to the addMe function.
Just like you did, you define a function and parameters like you did.
..and when to use the function .toString() by putting a period after
the variable and typing out the function.
When you want to place your function on a object so that all instances of that object can you that object.
In most cases, espcially when you are starting out. You don't have to worry about these prototypes. The way you did.
function addMe(number) {
return number+1
}
const answer = addMe(1) //2
Is a standard way of defining a function and calling it.
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)
I have a basic function taking an argument. I will use this argument to as index to access the array in JSON file. I want to take advantage of this argument instead of hard-coded inside the function. However, for some reasons, javascript is not return me the right value.
var obj = {
"first":[
["aaaaa"],
["bbbbb"],
["ccccc"],
["ddddd"],
["eeeee"]
]
}
I have a javascript function to access the file.
function addElement(ID) {
console.log(obj.ID);
}
and now if I use
addElement("first"); //this return me undefined.
I do not want to explicitly mention obj.first in order to access the right JSON object. I would like to make it more generic so that the method can be re-used. Am I missing anything here?
Thanks...
JavaScript supports both dot notation and a property name literal (obj.foo), and brackets notation and a property name string (obj["foo"]).* In the latter case, the string can be the result of any expression.
So you'd need brackets notation, not dot notation:
function addElement(ID) {
console.log(obj[ID]);
}
obj.ID accesses the property ID. obj[ID] accesses the property whose name is the string from the variable ID.
* Just for completeness: In ES6, it will support property name Symbols in brackets notation as well, but that's not relevant to your code.
I'm confused by the = vs. : when assigning a value to a property in an object
Now I know that there are a couple ways to create an object:
Object Literal
Object Constructor
With an object Literal you would use ":" to assign a value to a property:
var myObject = {firstName: "John", lastName="Smith" };
There we are using ":" to set the value to the property.
I also know a function itself is an object. And you can probably expose public properties from there as part of the function being an object?
So is it if you're assigning a function to a property that you'd use "="? I am assuming yet but what about something like this:
var phantom = require('phantom');
var World = function World(callback) {
phantom.create("--web-security=no", "--ignore-ssl-errors=yes", { port: 12345 }, function (ph) {
var phantomProcess = ph;
createBrowserPage = function(){
phantomProcess.createPage(function(page) {
this.headlessPage = page;
})
};
});
callback();
};
module.exports.World = World;
I assume I have this right in that I want to expose createBrowserPage through exports. I wouldn't use createBrowserPage: and use a ":" instead of "=" to assign that anonymous function to the createBrowserPage property right?
= is used for assignment in a Javascript statement as in:
variable = "foo";
: is used in an object literal declaration between a property name: value as in:
var obj = {
prop1: value1,
prop2: value2
};
If you want to expose your createBrowserPage() function through exports, you have several options, some of which involve creating an object and some of which involve assigning a property to an object. Which you choose and how you declare it leads to whether you use : or =. It depends upon which way you choose to write the javascript code that exposes createBrowserPage(). There is no single answer there. I will offer you a couple options.
If, in one statement, you want to assign one new property to the exports object, then you would use = like this:
module.exports.myFunc1 = myLocalFunction1;
If, in one statement, you wish to assign all your exported functions, then you would assign an object that was assigned with =, but used : in the declaration of the object like this:
module.exports = {
myFunc1: myLocalFunction1,
myfunc2: myLocalFunction2
};
In the first example, you are adding one new property to the exports object and assigning that property a value.
In the second example, you are declaring a new Javascript literal object (which uses prop: value syntax to declare its properties. And, then you are assigning that whole object to module.exports which actually replaces the entire existing exports object with a new one and this new object has two properties on it.
Your question is a bit confusing, but if you're interested in the precise meaning and grammar of : and = it's like this:
The colon (:) symbol is not an operator, it is part of the litteral object notation syntax and separates property names (a litteral string or simple identifier) from their value (any expression). Colons are only used in that context and as part of the trinary conditional operator (?:).
Something in curly brackets is parsed as a litteral object if and only if the { is not the first character in the instruction (otherwise it defines a block) and does not follow a function expression or declaration.
The assignment operator (=) (spec) is a binary operator, it can be used in any expression as long as its left operand is a valid left-hand-side expression, and it returns the value of the right operand. Unless strict mode is used, it will silently fail to assign a value to read-only properties.
I just can't understand how variables are passed, why are some passed by reference while other by value?
Example:
var a=4;
var b=a;
b=b++;
alert(a);//unmodified 4
var c=["t","ttt"];
var d=c;
d=d.sort(function(x,y){return (y.length-x.length);});
alert(c);//modified ["ttt","t"]
Where can I find a list of what variables will work like the first example and which like the second? (booleans, strings, etc... there are too many to test them all by miself)
JavaScript is always pass by value.
It's very common to say that objects in JavaScript are pass by reference, however that is not true. In a true pass by reference language, you could pass a reference to an object's reference, and have it point to another object. This is not possible in JavaScript.
Take, for example, C#. By default everything in C# is pass by value, just like JavaScript.
void foo(string s) {
s = "passbyvalue";
}
string a = "original value";
foo(a);
// a is still "original value"
However, if you alter foo to use pass by reference, the behavior changes:
void foo(ref string s) {
s = "passbyreference";
}
string a = "original value";
foo(ref a);
// a is now "passbyreference"
In JavaScript, only the first example is possible.
In JavaScript, everything is pass by value. This includes the object reference (yes, it is confusing). The reference itself is a value (it's very much like a pointer). It merely contains an id that allows the runtime to look up the object that is most likely stored in its heap. When you pass an object to a function, you are actually copying its reference into the function
It may be a seemingly small, and even anal, difference. But it's a key difference. Languages that have true pass by reference such as C# and C++ allow you to do things that are simply not possible in languages like JavaScript. The above trite example is one.
Imagine everything in JavaScript as an object. Object references are copied by value, but object properties are still used by reference. So:
var a = {};
var b = a;
b = 'Blah';
console.log(a); // Still {}
and
var a = {};
var b = a;
b.test = 'Blah';
console.log(a); // Is now {test: 'Blah'}
To simplify things a little: properties are by reference, values are by value.
Usually you can check the method on MDN. For example, the sort method's documentation states (emphasis added):
Sorts the elements of an array in place and returns the array.
The "in place" there says it will modify the array.
All primitives (for example, numbers and booleans) are passed by value; all objects are passed by reference, although some (like String objects) are immutable (although still passed by reference).
All objects get passed by reference and values by value. (technically this is not true, but it explains the behaviour)