The concept of functions being objects in JavaScript would be ok with me if I could understand the following question. I have searched around and looked into the javascript engine to try and find the answer, but no explanation I've found so far sits well in my mind...
An object like the one below is understandably layed out in a hash map type of construct.
var person = {
firstName:"John",
lastName:"Doe",
age:50,
eyeColor:"blue"
};
However, to say this is also an object is where I get stuck:
var name = function () {
alert ('name');
}
In terms of memory, how is this function stored?
Are the statements inside the "hash map" of a function layed out in an execute order? So each property is called upon after the other?
I'm probably missing something or visualising something wrong.
Thanks.
P.S
To clear up question 2,
Say I have an if statement inside my function... will that be stored in a property accessible through one of its properties?
Every object in javascript has properties (key-value pairs identified by strings or symbols) and it has internal slots.
The function object name is stored in the same format as the person object, but their internal slots differ.
person's properties are firstName, lastName, age and eyeColor, each holding the respective primitive value
person's internal slots are (amongst others):
[[prototype]], pointing to Object.prototype
name's properties are name, prototype and length (as typical for Function instances)
name's internal slots are (amongst others):
[[prototype]], pointing to Function.prototype
[[ECMAScriptCode]], pointing to the code of the function
[[Environment]], pointing to the scope the closure was created in
Disclaimer: That's only how it behaves, engines may implement this however they want. Still, it serves well as a mental model, and it's important to understand that objects have a layer below the publicly visible properties.
Functions are objects, in that they can have properties and methods. Unlike objects, they can also be called and will always return a result.
Note that the ECMAScript (i.e. JavaScript) language specification describes how Function objects should behave rather than underlying implementation, so the in-memory representation of the object will depend on implementation.
Regarding 2: Note that the full text of a Function might be stored in the functionBody property, however the body of a Function does not have to be JavaScript. It could be native code, for example, that is not meaningful to return in a string.
If you just want to do regular JavaScript coding, I don't think you really need to worry about how the function is stored by the browser or server or whatever. I do think you are misunderstanding the object-nature of a function. The lines of code inside the function are not individual parts of a hash map. Rather (and this only begins to touch on the concept), a function can have properties with names and values just like a regular object can have such properties. The following code demonstrates this.
var myFunc = function() {
var x = "hello".toUpperCase();
document.write('<p>' + x + '</p>');
};
myFunc.favoriteColor = "red";
myFunc(); // runs the function and shows the text "hello"
document.write("<p>" + myFunc.favoriteColor + "</p>"); // shows the text "red"
The answer to 1. is: It depends on the implementation.
The 2nd question doesn't make any sense.
I think you are looking at the syntax, and assuming that because the way data is declared, and the way functions are declared, that a function can be treated as data in the language.
This is not the case.
There are languages where this IS the case. Lisps and Prolog being the most common examples. see:
https://en.wikipedia.org/wiki/Homoiconicity
Related
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've noticed ## used in a few pages about new ES6 features, but I don't know what exactly it means (whether it's actually syntax or just some kind of documentation convention). And it's hard to google. Can someone explain it?
## describes what's called a well-known symbol. (Note that it isn't actually valid syntax in JS.) According to the ES6/ES20151 specification:
Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm. Unless otherwise specified, well-known symbols values are shared by all Code Realms (8.2).
Code Realms refer to different instances of a JavaScript environment. For example, the Code Realm of the root document would be different to that of JavaScript running in an <iframe>.
An example of where it matter what code realm an object comes from is when trying to use instanceof to determine whether an object is an array (hint: it won't work if it's from another frame). To avoid these kinds of issues from popping up with symbols, they are shared so that references to (say) ##toString will work no matter where the object came from.
Some of these are exposed directly through the Symbol constructor, for example, ##toPrimitive is exposed as Symbol.toPrimitive. That can be used to override the value produced when attempting to convert an object to a primitive value, for example:
let a = { [Symbol.toPrimitive]: () => 1 };
console.log(+a); // 1
console.log(a.valueOf()); // (the same object)
console.log(a.toString()); // "[object Object]"
In general, symbols are used to provide unique properties on an object which cannot collide with a random property name, for example:
let a = Symbol();
let foo = { [a]: 1 };
foo[a]; // 1
There is no way to access the value except by getting the symbol from somewhere (though you can get all symbols for an object by calling Object.getOwnPropertySymbols, so they cannot be used to implement private properties or methods).
1: See this es-discuss topic for some discussion about the different names.
As per the understanding, The main purpose for the existence of prototype property in a function type object is to allow properties/methods sitting under prototype to get inherited by other objects. This enables prototypical inheritance.
Considering window['Number'] function type object,
In general, Idea is to understand the thought process on what comes under prototype. So. I would like to take a specific example i.e., Number, with below questions.
From design perspective, how would I understand,
1)
why parseFloat()/parseInt()/isFinite()/isInteger()/isFinite()/isNaN()/NEGATIVE_INFINITY/NaN
are part of function type object Number?
2)
why methods toExponential()/toFixed()/toPrecision() are part of Number.prototype object?
Note: Have an idea on class based inheritance using java syntax, where both static/instance members can be inherited.
If you understand classic class based inheritance, then Number.parseFloat is a static class method, while Number.prototype.toFixed is an instance method. The "class methods" do not need an instance of Number to work, you simply call them directly as Number.parseFloat(foo). Instance methods on the other hand require an instance first:
var foo = new Number(bar);
foo.toFixed();
Properties declared on the prototype object are visible from all instances. Thus:
var n1 = new Number(1), n2 = new Number(2);
Those are two instances of Number, and via each instance it's possible to call the functions on the Number prototype:
alert( n2.toExponential() ); // "2e+0"
Because of the way that function invocation works in JavaScript, the .toExponential() function in that example will be invoked with this referring to the number instance used to make the function call — n2 in this case.
Now, the .toExponential() function could have been defined as a property of the Number constructor itself, but then the parameter would have to be passed explicitly (like Number.toExponential(2)). That's not how the runtime was designed, however. As with so many "why?" questions about how languages and APIs work, it's ultimately just a design preference on the part of the language designers. It should be clear that something like .parseFloat() would really not make any sense as a prototype method, because the whole point of .parseFloat() is to turn something that's not a number into a number. (It could have been added to one or more other prototype objects, but again the preference of the language designers was to just make it a callable function on the Number constructor itself; that's a recent ES6 addition to the spec of course.)
Finally note that in the particular case of the Number constructor, it's pretty rare that you'd actually explicitly instantiate a number object. Generally that happens implicitly when a number primitive value is used with the . or [ ] operators as if it were an object reference. Primitives are not objects, but the language automatically wraps a primitive value in a Number object in those cases, so the first example above would work the same if it were written like this:
var n2 = 2;
alert(n2.toExponential());
The variable n2 has a plain primitive 2 in it, but that will be wrapped in a Number instance in order to allow the method call.
I do not know whether you mean a program design perspective or a language (core library) design perspective, so I'll try to answer both.
Before we begin, please forget "class" or "instance" or "static".
JavaScript is not class based.
There only object and inheritance.
Now, let's see the object diagram.
Note that new Number does not inherits Number.
Neither prototype nor constructor is an inheriting relationship.
This means number instances inherits toExponential, toFixed, etc. but does not inherits parseFloat, parseInt etc.
So you call them like Number.parseFloat() and new Number(n).toFixed().
This is how JS is designed. If you don't like it you can design your own Number library.
For example, you may create your own Number that has toFixed methods on the Number object rather than on its prototype object, like this:
var SheepyNumber = {
toFixed: ( n ) => Number.toFixed( n )
}
SheepyNumber.toFixed( 3.14159265358979323846 ) // Evaluates to '3'
Do not add toFixed to Number object. It may work for now,
But if later specifications introduces this function with any different in parameter or logic,
then your program may break when you use the standard implementation,
or a third party library may break if you keep your own implementation.
Either way, you lost.
Which leave us the question, why does JS not put toFixed to Number, like we just did, but instead put toFixed to Number.prototype?
The obvious answer is this is more object-oriented.
Since new Number has an internal value property, toFixed can take that value, instead of taking in an extra argument.
The real answer is no one knows.
JavaScript copied Java for its core API - you can find most of these methods in the Java Float class.
Some of these Java methods are instance methods (corresponds to methods on Number.prorotype), some are static (corresponds to methods on Number), but most are both - including a counterpart of toFixed.
Why JavaScript did not put isFinite or isNaN to Number.prototype?
Why did no browsers implement toFixed on Number which can co-exists with the one on Number.prototype, during the first browser war that shaped the JavaScript as we know now?
Language design is an art.
And you may not always know who is responsible or why, because it has been shaped by many hands.
Is it acceptable to add an attribute or value to a JavaScript function?
Example:
var f = 1;
function foo (param) {
f++;
}
var fooFunc = foo;
fooFunc.dummy = f;
console.log('fooFunc: ' + fooFunc);
console.log('fooFunc.dummy: ' + fooFunc.dummy);
The above example creates a function (foo), then assigns it to a new variable (fooFunc) and then adds a dummy attribute to fooFunc.
When run, this example prints the text of the function first, and then it prints the expected value (1 in this case). When printing the function, it doesn't show any indication of the dummy value:
fooFunc: function foo(param) {
f++;
}
fooFunc.dummy: 1
JsFiddle here - open the browser's JavaScript console to see the log messages: http://jsfiddle.net/nwinkler/BwvLf/
Why does this work? And where is the dummy attribute stored, and why isn't it printed when I log the function?
Lastly, even if this works, is it a good idea (or an acceptable practice) to use this? I don't want to start an open ended discussion on this, but rather see if there's documented uses of this, or people discouraging this in JavaScript coding guidelines.
Everything except primitives ( null, undefined, number, string, boolean ) in JavaScript are objects. So functions are basically objects.
Objects in JavaScript can have properties and methods, hence functions too.
all functions inherit from Function.prototype and has certain properties ( name, length ) and methods ( .call, .apply ) coming through this chain.
It is sometimes very useful to keep properties attached to the function itself, like cache information, number of invocations etc. There is nothing wrong out in using it this way.
More details : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
Let's have a look at ECMAScript documentation (Which is the standard JavaScript is based on). Here's the 3rd. version of it:
http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf
Go to chapter 15, Native ECMAScript Objects.
15.3 > Function objects.
There's a lot of interesting information there concerning your question, but the first thing worth noticing is that function is an object.
As an object, it has attributes (predefined and that you can assign yourself).
For example, try:
console.log('fooFunc.name: ' + fooFunc.name);
It should display "foo" in your case.
Since it's documented quite well, you can use it as a standard way, though it is not so well-spread and may seem a bit unusual.
Hope this helps.
It is normal object behavior, whether "acceptable" or not.
By using the function keyword you are actually calling the native predefined Function() constructor. Like any object constructor it returns an object after building it. Like any object, the returned object can have properties, including other functions as method properties.
var adder = function(a, b){return a+b};
adder.subtracter = function(a, b){return a-b};
console.log(adder(1,2)); // 3
console.log(adder.subtracter(1,2)); // -1
TIP: if you want to see the adder object and its subtracter method, switch to DOM view from Console view after running the above code in console and then search for "adder". You'll see the object there, and then you can collapse to see what it's made from, including a subtracter object.
Of course, a function object is a special native object, which makes it possible to make calls like this: adder() and actually run some code. The fact that a function object is harder to inspect for custom attached properties, combined with its native special object treats (read built-in restrictive behavior), should give you a hint that, while it's possible, attaching custom properties is not the intended nor a good use of a function object.
I have an array of objects that I generate from JSON.parse. I access its properties like this:
AnObject['PhoneList'][i]['PhoneLabel']
When I run the code through the google closure compiler, the name of the properties is not obfuscated and clearly visible. Why are the names of object properties not obfuscated?
Google closure has a difficult time figuring out what it can and can't rename. For example, any data structure that is created or referenced by code outside the Google closure compiled code cannot be renamed or the two sides won't be expecting the same code. Further, referencing properties via constructed strings makes it next to impossible for closure to do it's job well. As such, Closure has a whole bunch of rules and settings to help you control this and direct it for what to do. I'd suggest you read up on those rules/settings at these references:
https://developers.google.com/closure/compiler/docs/api-tutorial3
https://developers.google.com/closure/compiler/docs/compilation_levels
https://groups.google.com/group/closure-stylesheets-discuss/browse_thread/thread/386ba6db27a43887?pli=1
https://developers.google.com/closure/compiler/docs/limitations
And, quoted from this last reference:
String representations of function or parameter names:
The Compiler renames functions and function parameters but does not
change any strings in your code that refer to functions or parameters
by name. You should thus avoid representing function or parameter
names as strings in your code. For example, the Prototype library
function argumentNames() uses Function.toString() to retrieve the
names of a function's parameters. But while argumentNames() might
tempt you to use the names of arguments in your code, Simple mode
compilation breaks this kind of reference.
Quoted strings is the syntax used for properties that should not be renamed ("exported").
you probably want to use
AnObject.PhoneList[i].PhoneLabel
instead.
Google Closure Compiler doesn't touch quoted strings.
myObj.prop = 3;
will result in prop being renamed (and myObj too perhaps)
myObj['prop'] = 3;
will result is 'prop' remaining untouched.