I've been using JavaScript for a short period of time, and have found myself interested as to whether or not there is any correlation between the . syntax used for referencing children of an object, and functions such as console.log.
And was interested whether functions such as this, were in a way objects behind the scenes, with log being a method inside of a console object, and if I am just referencing the child of an object.
Or another example, the .length method, is this just a hidden property of the object or array you are referencing.
Apologies if this is poorly worded, I was struggling to write down my train of thought, and I would be incredible appreciative if anyone could let me know if this is how methods such as these are structured, or if I am thinking of them in completely the wrong way.
Notice how you can access the length property on a string. While string is a primitive, the length property actually exits on a wrapper object that is created temporarily when we try to read .length.
Arrays and other collections have this property, because they are objects themselves.
Hope this helps to clarify a bit!
console.log is not a function, per se. The function is the log property on the console object. console is an object with many methods:
To access it's method, just like to access any property of a JS object, you can use dot notation or square bracket notation
var log = console.log;
log('hello');
var logSquare = console['log'];
logSquare('hello');
// or just do
console['log']('hello');
Except for primitives, everything in JS is an object.
Related
Are arrays merely objects in disguise? Why/why not? In what way(s) are they (such/not)?
I have always thought of arrays and objects in JS as essentially the same, primarily because accessing them is identical.
var obj = {'I': 'me'};
var arr = new Array();
arr['you'] = 'them';
console.log(obj.I);
console.log(arr.you);
console.log(obj['I']);
console.log(arr['you']);
Am I mislead/mistaken/wrong? What do I need to know about JS literals, primitives, and strings/objects/arrays/etc...?
Are arrays/objects merely strings in disguise? Why/why not? In what way(s) are they (such/not)?
Arrays are objects.
However, unlike regular objects, arrays have certain special features.
Arrays have an additional object in their prototype chain - namely Array.prototype. This object contains so-called Array methods which can be called on array instances. (List of methods is here: http://es5.github.com/#x15.4.4)
Arrays have a length property (which is live, ergo, it auto-updates) (Read here: http://es5.github.com/#x15.4.5.2)
Arrays have a special algorithm regarding defining new properties (Read here: http://es5.github.com/#x15.4.5.1). If you set a new property to an array and that property's name is a sting which can be coerced to an integer number (like '1', '2', '3', etc.) then the special algorithm applies (it is defined on p. 123 in the spec)
Other than these 3 things, arrays are just like regular objects.
Read about arrays in the spec: http://es5.github.com/#x15.4
Objects are an unordered map from string keys to values, arrays are an ordered list of values (with integer keys). That's the main difference. They're both non-primitive, as they're composed of multiple values, which also implies pass-by-reference in JavaScript.
Arrays are also a kind of object, though, so you can attach extra properties to them, access their prototype and so on.
In your revised example, you're only taking advantage of the fact that an array is actually an object, i.e. you can set any property on them. You shouldn't do that. If you don't need an ordered list of values, use a plain object.
Strings can be either primitive or objects, depending on how they were declared.
var str = 'yes';
Gives you a primitive, while,
var str = new String('yes');
will give you a String object.
All arrays are the same (Whether or not they were defined with [] or new Array()), are of the type object and inherit from the "Array" object's prototype. There aren't real classes in Javascript, everything is an object, and there's a system defined object called Array. It has a property called 'prototype' (of type object), and when you use the new keyword on an object with a prototype property, it creates an instance with a reference to the contents of the prototype and stores it in your variable. So all arrays you've ever used in Javascript are objects and instances of Array's prototype property.
In any case, although arrays really are objects, they behave like arrays because of their useful properties and functions (Such as length, slice, push etc).
Another note, although I said there are no classes, when you do this:
console.log(Object.prototype.toString.call(your_object));
it will give you a string in the form [object Object]. But what's useful is that when you call it with an array, you get [object Array] same with functions which give [object Function] and a number of other system defined types, which assists in differentiating between normal objects and arrays (Since the typeof operator will always just return the string 'object').
Try this
var a = Array;
and go into firebug and examine the contents of a, especially it's 'prototype' property.
Edit: Changed the wording a bit, to be more correct. In fact when you use the new keyword, it creates an instance which references the prototype object. So any changes made to the prototype after the instance's declaration, will still affect the instance.
Edit: In answer to your latest revised question (are arrays/objects actually strings in disguise): No. They are objects, as I've explained. Strings are either a primitive type, or an object type (An instance of the String object) which contains the primitive equivalent as one of it's properties.
Arrays are not primitives in Javascript, they are objects. The key difference is that as a result, when you pass an array to a function it is passed by reference, not by value.
So yes! Arrays are objects in javascript, with a full blown Array.prototype and everything (don't touch that though...)
The confusion comes from the fact that javascripts lets you access object attributes in two ways:
myObj.attribute
or
myObj["attribute"]
Really what makes an array an array has nothing to do with the way you store data -- any object can store values using the syntax you use to store the array -- what makes an array an array is the fact that array methods (e.g. shift() and sort()) are defined for Array.prototype.
Trying to be brief with what I believe to be of the most significance: arrays have a number of methods that objects do not. Including:
length
push
pop
An object declared as var x = {foo:bar} has no access to a .length() method. They are both objects but with the array as a sort of superset with methods mentioned as above.
I don't feel I this is even close to being of Crockford standard in terms of explanation but I'm trying to be succinct.
If you want to get some quick results, open up Firebug or your javascript Console and try Array.prototype and Object.prototype to see some details
Update: In your example you declare an array and then do:
foo['bar'] = 'unexpectedbehaviour';
will produce unexpected results and won't be available in simple loops such as:
var foo=[0,1];
foo['bar'] = 2;
for(var i=0;i<foo.length;i++){
console.log(foo[i]);
}
//outputs:
//0
//1
An array can accept foo['bar']=x or foo.bar=y like an object but won't necessarily be available to be looped through as highlighted above.
Not that I'm saying that you can't iterate through the properties of an object, just that when working with an Array, you're utilising that unique functionality and should remember not to get confused.
In JavaScript you have a few types, everything else is an object. The types in JavaScript are: boolean, number, and string. There are also two special values, "null" and "undefined".
So the quest "is a JavaScript array an object?" is slightly ambiguous. Yes, a JavaScript array is an "object" but it is not an instance of "Object". A JavaScript array is an instance of "Array". Although, all objects inherit from Object; you can view the inheritance chain on the MDC. Additionally, arrays have slightly different properties than an object. Arrays have the .length property. They also have the .slice(), .join(), etc methods.
Douglas Crockford provides a nice survey of the language's features. His survey discusses the differences you are asking about. Additionally, you can read more about the difference between literals and constructors in question #4559207.
Arrays are Objects, but of a specialized nature. Objects are collections of values indexed by keys (in Javascript notation, {'key': 'value'}), whereas Arrays are Objects whose keys are numeric (with a few functions and properties). The key difference between them is obvious when you use a for each loop--an Object will iterate over all the values in its properties, whereas an Array will return the keys instead. Here's a link to a JSFiddle demonstrating the difference--notice that the first for each, which uses an array, returns the indexes, not the values; in contrast, the second for each returns the actual values at those keys.
I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.
I wanted to be able to create an object that had it's own intrinsic value. That way I could use it in an expression as if it was a regular variable. It turned out to be quite easy - so easy I am wondering if I am missing something. All it seems to take is to make sure the object contains a method "valueOf". Like so:
var p = {
a: 12;
valueOf: function(){return this.a+12}
}
alert(p/3); // =8
It's probably a good idea to include a "toString" method too. What seems to be happening is that without the valueOf method, a reference to the object goes up the prototype chain until it finds the method on Object, which just returns "object Object". By providing a local one, the method can return anything.
It seems to work in all browsers that I tried.
It is really another way to provide a getter-like functionality. But a little better because getters can only be applied to properties of objects. This way you can use the object itself.
What do you think? Is this safe? Any pitfalls?
Well I started using this pattern and found one issue. If you create an object p like the one above, you have to guess how the interpreter will view a reference to the object.
For example, if P is used in arithmetic expression, it calls the object's valueOf() method to get its value. But when you try to access a property of p such as p.a, then it treats p as an object and retrieves the property as you expect.
In a getter, by contrast, accessing p.a when there is a getter on p would first run the getter and then try to get the property 'a' of the result. Subtly different, but important.
It's all quite correct and seems to "guess" correctly what to do. But using the pattern does rely on knowing this behavior, which AFAIK is not documented anywhere.
Every time I assign a string, I'd actually like to assign a string object, without the extra code.
This var foo = "bar";
becomes var foo = new String("bar");
Basically hi-jacking the assignment.
Follow-up:
If the above is not possible is there a way to prototype the string variable type, rather than the String object?
As pointed out by armando, the foo would be a string type, but is essentially a customized array. It would be nice to be able to prototype functions to that class.
No this is not possible
If it was possible, you really would not want to do this, at least not globally.
The string variable type does not have all the extra overhead that an object does.
Note: the string array that is created (in your case, foo) would have other properties (eg foo.length)
Objects come at a performance hit
It's not quite what you're looking for, but you may want to look at Overriding assignment operator in JS
My JavaScript code stores a lot of data in arrays. I want to retrieve a key using something similar to what I wrote below. It key that should be retrieved is based on variables that are page-dependent . The following code doesn't work. Can anyone give me a solution to this problem?
This is part of a script that does automatic conjugation. (looks for SUBJECT in a div and then looks for VERB in another div and then conjugates the verb by retrieving the conjugated form from the array)
function getarray(Array,Key) {
return Array[Key];
}
Example of how it should work:
verb = innerhtmlfromdiv;
subject = innerhtmlfromotherdiv;
function getarray(Array,Key) {
return Array[Key]; }
conjugatedverb = getarray(verb,subject);
htmltextbox.value = conjugatedverb;
First off, what you want is an Object, not an Array. I'm guessing that you're new to javascript and your previous language was either PHP or PERL, and so you think what you're using is an "Associative Array".
The basics: There is no such thing as Associative arrays in Javascript. There is Objects, and a non-primitive subclass of Object called Array, which has some methods for dealing with Numericly named object properties, and a magic length property.
Since the keys you are dealing with are strings, not numbers, you have no use for Arrays.
Javascript Objects on the other hand are similar to an Associative array in php, or a hash in perl. (but they are not exactly the same thing).
As you have no doubt discovered, with an Object, you can use subscript notation to access certain properties, as in
verbs["go"] = "went";
this is equivilent to
verbs.go = "went";
a common mistake is to think that the dot notation is only used for objects, and the subscript notation for "associative arrays", because this is how it works in PHP. In javascript the two notations are interchangable. Since Arrays are a subclass of Object, the above examples work on them as well (but they don't use any special properties of Arrays).
As for your specific problem:
You need an object full of objects.
so for instance
var verbs = {
"do":{"Truck":"Drive","Blender":"Turn On","Bike":"Ride"},
"take":{"Money":"Steal","Julie":"Accompany","Lever":"Pull}
}
then your function would be:
function conjugate (verb, subject) {
return verbs[verb][subject];
}
and an example of its use would be
conjugate("do","Truck") // returns "Drive"
Try changing the parameter name Array to something else. Array is the name of a built-in function/object in javascript.
I don't quite get the point of the function. This is like writing:
function getValue(var) {return var}
Why not just get the value the normal way without wrapping it in a useless function:
conjugatedverb = verb[subject];
htmltextbox.value = conjugatedverb;
Also, your code doesn't make sense when you claim to do an innerHTML from an element and somehow get an object instead of a string. What is really going on? I think your problem starts even before this snippet of code.