From what I have understood, primitive data types such as a string can also have properties ie string can have .includes . Does that mean all primitive data types are converted to objects before being executed. If yes, what is the point of having distinct difference between primitive data types and objects.
Whenever you try to refer to a property of a string s, JavaScript converts the string value to an object as if by calling new String(s). This object inherits string methods and is used to resolve the property reference. Once the property has been resolved, the newly created object is discarded.
Numbers and booleans have methods for the same reason that strings do: a temporary object is created using the Number() or Boolean() constructor, and the method is resolved using that temporary object.
source Javascript: The Definitive Guide. David Flanagan
When you call a property on a string (lower case) primitive, the JS runtime creates a new instance of a String (upper case) object and copies the string primitive value into the new "wrapper" object, then the property or method that you originally called gets called on the wrapper object and then that wrapper object is garbage collected when the statement is completed. This makes it only seem like some primitives have properties when they actually don't.
If yes, what is the point of having distinct difference between
primitive data types and objects.
The point is that primitives are lightweight entities that have a low memory footprint, whereas Objects can do more and therefore require a larger memory footprint. Also, you can't inherit from a primitive, whereas you can from an Object.
If you'll only be doing limited Object operations, using a primitive is the best approach, but if you know that you'll be using many properties of an Object, it's more efficient to create the Object using a constructor from the start to avoid the constant creation and destruction of wrapper objects.
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.
In javascript only object and arrays are mutable and remaining are primitive type which are immutable. However if we create an object of string,then it can't be mutated.
why is that?
var a = new String("abc")
a.toUpperCase();
console.log(a) /*wont print "ABC" and prints an object with String:abc. Concludes
that string object is immutable.*/
In general, yes, objects are mutable.
The reason that "string objects" - created with new String - are not mutable is that string objects result in objects which have an internal StringData property:
Set S.[[StringData]] to value.
That StringData is what is retrieved when the string object is coerced back to a primitive.
If the interpreter provided a way to change this StringData internal slot - then these sorts of objects would effectively be mutable. (Similarly, Set.add changes a Set's internal slot, and the same sort of mechanism exists for many other objects in JS - an exposed method changes values held in internal slots.)
But
a.toUpperCase();
alone wouldn't do anything - toUpperCase returns a new string. There are no methods (in standard implementations) that exist that can alter a string object's StringData internal slot - all you can do is create a new string object with a different StringData.
You could also strongly consider just not using string objects at all.
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.
At one popular blog, the author asked his audience what was their “Ah ha!” moment for JavaScript and most of the people said that it was realizing that everything in JavaScript is an object.
But being new to JS and programming in general I don't quite get what that means. It doesn't seam like it's related to actual JS Object - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
Or it does?
If it doesn't could you please explain what do they mean by "everything in JavaScript is an object".
Or it's all about OO Programming in general and reading something on this subject will help to understand it? Can you recommend what to read on this topic?
Go back to first principles.
What's an object? It's a software component that encapsulates state and behavior together into a single entity in memory.
By that definition, you can see where everything can be thought of as an object. Functional programmers make functions first class objects. Data folks would say that data, even that without behavior, can be thought of as an object (albeit not a very smart one).
I don't see what this changes.
JavaScript treats functions as objects.
I'm not sure what effect this insight will have on your programming.
What they mean, most likely, is that any data that can be assigned to a variable has properties (and therefore methods) that can be accessed in an object like fashion.
// strings
"asdf".length; // 4
"asdf".replace('f', 'zxc'); // "azxc"
// numbers
(10).toFixed(2); // "10.00"
// booleans
true.someProp; // undefined (point is it doesn't crash)
They even have prototypes they inherit from.
"omg".constructor; // function String() { [native code] }
String.prototype.snazzify = function() {
return "*!*!*" + this + "*!*!*";
};
"omg".snazzify(); // "*!*!*omg*!*!*"
However, these are primitives, and while they behave object like in a lot of ways, they are different from other "real" JS objects in a few ways. The biggest of which is that they are immutable.
var s = "qwerty";
s.foo; // undefined, but does not crash
s.foo = 'some val'; // try to add a property to the string
s.foo; // still undefined, you cannot modify a primitive
Do note though that functions are real mutable objects.
var fn = function(){};
fn.foo; // undefined
fn.foo = 'some val'; // try to add a property to the function
fn.foo; // "some val"
So while it's not technically true that "everything in JS is an object", under most circumstances you can treat them mostly like objects in that they have properties and methods, and can potentially be extended. Just be sure you understand the caveats.
NOT everything in JavaScript is an object.
All data in JavaScript must fall into one of six primitive types, or the object type. Primitive types includes boolean, null, undefined, string, number and symbol; everything that is not a primitive is an object.
This means functions are objects, arrays are objects, ES6 classes de-sugars into a function which are objects.
The confusion arises because primitive values have object wrappers. When you try to access the length property on the string literal, JavaScript creates a temporary object wrapper around the primitive and access the length property of that object wrapper. After the property has been retrieved, the object wrapper is discarded. This is known as autoboxing.
Essentially, it is implemented similar to the following:
const foo = "bar";
// When you run `foo.length`, it's similar to
tmp = String(foo);
tmp.length;
delete tmp;
Or
const foo = "bar";
(new String(foo)).length;
The string, number and boolean primitives have object wrappers, but null and undefined do not. So trying to access a property or method from those primitives would throw an error.
null.length; // Uncaught TypeError: Cannot read property 'length' of null
undefined.length; // Uncaught TypeError: Cannot read property 'length' of undefined
Not everything is an object in JavaScript. For example a number is not an object.
Different languages have different definition of "object". For JavaScript, the official definitions can be found in the ECMAScript Language Specification, which states:
In ECMAScript, an object is a collection of zero or more properties
each with attributes that determine how each property can be used (...) Properties are containers that hold other objects,
primitive values, or functions. A primitive value is a member of one
of the following built-in types: Undefined, Null, Boolean, Number,
BigInt, String, and Symbol; an object is a member of the built-in type
Object; and a function is a callable object.
So by this definition it is clear that primitive values (like numbers) are not objects. Even strings are not objects, which is different from most other OO languages.
So why do some people say "everything is an object"? You have to ask them! But I suspect it is because they are getting confused by the built-in objects Number, Boolean, String etc. which can be used as wrappers around the corresponding primitive values. This wrapping sometimes happen automatically, which can make primitive values look like object and for example allow you to (seemingly) access properties on primitives. But in reality the properties are on the wrapper object.
'ALMOST everything is an object' because the MAIN code-units are JS-objects. On primitives you can NOT add members for example as on all objects. My answer why JS-functions are JS-objects here: https://stackoverflow.com/a/24811539
When an object is passed into a function, the object is passed by value (although the value for an object is a reference). I am passing very large objects into my functions, but only accessing a handful of properties (6-12) from within the function. Memorywise, would it be better to only pass the properties instead of the whole object? Or would this actually create more of a memory issue if my properties are strings?
Given the two functions below, what happens memorywise? In f1, does javascript/v8 create a new object foo in memory or is it really just a pointer? Does it remain just a pointer if I access a string property or does V8 then make a copy of that string for use within the function. In f2, I assume that a completely new copy of the string foo is made for the function. Is this a correct assumption?
function f1(x) {
var y = x.foo;
}
function f2(foo) {
var y = foo;
}
var obj = {foo: "test"};
f1(obj);
f2(obj.foo);
"Memorywise, would it be better to only pass the properties instead of the whole object? Or would this actually create more of a memory issue if my properties are strings? "
That would require more memory. Doesn't really matter if they're strings, since strings are generally implemented as Reference Types as well, but for each argument, there will be a copy of the value instead of just a single copy of the Object reference.
The object reference is very light weight, so you just as just copy that instead of all individual members of the object.
Also, this will be required if you rely on mutations of the object within the function.
In your examples, there's only one property being passed (a string). If your code doesn't rely on mutations of the object itself, then there'll be no significant difference between the two.
In the example that passes the object, the only copy is the object reference. It isn't a pointer, but it is very light weight, and nothing to be concerned about.
In the example that passes the string, it would seem as though it makes a copy of the entire string, but since stings are immutable in JavaScript, implementations generally implement them as reference types as well.
Therefore it's as efficient to pass a single character string as it is to pass a 10,000 character string.