Read codebase of javascript function - javascript

I just realize that I can use the function console.log to read a codebase of any javascript function. Anyone how it happens? and what behind the sense of this action (read codebase)
Example:
Open chrome console and paste this code
function superMan(){
var i=i+1;
var j=i+1;
}
then you use the function console.log like console.log(superMan) and you can see the codebase of SuperMan

In javascript, When a program is run a execution context is created. There are 2 phases in which its created namely below.
Creation phase
Execution phase
What you are referring to in the question is mostly related to the creation phase. In this phase all the variables are declared and initialized to undefined ( incase of var) and for variables with let and const they are declared in the Temporal Dead Zone and are unreachable and only reachable when the code is executed in execution context.
For functions(specifically Function statements and not function expressions) these are taken in as it is in memory and stored. So, when you try to log in the function in console.log it shows the variable in memory. This will be also true for function expression once the execution runs over it(since before its treated like a normal variable and not function). They will be showed as it will now be pointing to the function directly assigned to that variable. Also, You need to understand function in Javascript are first-class functions meaning it can be passed and treated like a normal variable (containing a number) and so.

It's part of the spec but a good reason to use it is in edge-cases where the code of the function could be important to its execution (usually for an API, interface or some form of abstraction) where you need to know a bit more about the function before acting upon it. There are many use-cases, but it can be particularly useful to try to detect and handle edge-cases for a transpiler (the code you write isn't verbatim to the code that the browser sees)

Related

How does Javascript runtime identify setTimeout() as a WEB API?

When javascript runtime finds setTimeout() method, it sends it to Event table. How does runtime know that setTimeout() is a WEB API? Does it first look for setTimeout() method in the current context and then if not found assumes it as a WEB API?
When javascript runtime finds setTimeout() method, it sends it to Event table.
JavaScript doesn't "know" or care what setTimeout does. :-) It's just that setTimeout is one of the functions defined in the host environment provided to the JavaScript engine by the host (the browser, in your example). When you use JavaScript to call the function, the function's implementation (provided by the host environment) is executed with the information you provide. It's the host, not the JavaScript engine, that knows what to do with the arguments you provide to setTimeout.
When the host (the browser or Node.js or whatever) needs to create a new runtime environment (for instance, for a window), one of the things it does is create an object to be the host-provided global object for that environment (more properly called a realm), including putting any properties on that object (like setTimeout) that provide host-defined features. It provides that object to the JavaScript engine via what the JavaScript specification calls the InitializeHostDefinedRealm abstract operation. When the JavaScript engine runs your code that uses setTimeout, it sees the identifier setTimeout and looks in the current execution context to see if setTimeout is defined there; if it isn't, the engine looks at the parent execution context, and so on, until it reaches the global execution context, which gets its globals from the host-provided global environment (in part; it also has other globals). So, having found the function matching setTimeout, the JavaScript engine calls that function — which runs the host-defined code for the function, which sets the timer.
So the JavaScript engine doesn't know what setTimeout does, just that there is a setTimeout function on the global object it got from the host.
In terms of identifying which function to run, it doesn't make any difference whether a function is built into the engine, or added at run-time (this fact is really useful, allowing functions to be "polyfilled" if the engine doesn't provide them).
When you write foo(), JS actually looks for a variable with that name (this unification of variables, properties, functions and methods is an unusual feature of JS). It looks for it first in the local scope, then in the parent of that scope, and so on up the "scope chain".
The last place it looks is the "global object", which in a browser is the window object. So if you define window.foo as a function, you can call foo() from anywhere that doesn't have its own function called foo in scope.
Built-in functions work just the same way: when the JS engine starts up, it (conceptually) defines a whole bunch of functions on the window object, with special implementations referring to internal operations in the engine rather than composed of JS code.
So when you call setTimeout, JS walks up the scope chain, and if it doesn't find anything else, will find the setTimeout function registered by the engine, and runs it. The engine then does whatever it wants to do with that - hopefully, something that complies with the behaviours described in the current ECMAScript standard.

JavaScript : Please Explain this weird behaviour

Just Started learning about JS.
CASE-1 Please look at the below given image.
My Understanding for this behavior : JS interpreter on reaching line 9 which commands to execute function a(); will create a new execution context for function a (or we can say allocate memory in heap for execution context which is an object and point this to it, right ??). Now i know that interpreter will first go through the whole function body and will allocate space for variable declarations and function declaration, in the execution context created in heap. This is evident from the right side of the image where in local Scope we have a reference variable b to the lambda of function. And now after having a pass through whole function body interpreter will execute code. Now since we already have the function b stored in a's execution context (or a's execution context knows about b),it will execute it. (This is what hoisting is, right ??)
So far so good. But,
Now look at this image :
Now if according to my concepts which i mentioned above,
On right side inside Local we must have a variable b referencing to function lambda, but its not.
What am i missing ??
Is my concepts wrong ??
Is it because of Chrome console ??
Can you explain this behavior ??
CASE-2 : Ok Then i did another experiment to know the behavior of Interpreter :
In both of the above given images, we have space allotted to variable a referencing to lambda of function, in both cases. This is completely opposite behavior to case-1.
Can you explain this behavior ??
Small Request (If you can..): If you can use the terms stack/heaps/memory/execution context object/link/pointers instead of Lexical environment, scopes, closures, chain etc etc it will be much preferred since they all are quite confusing. Its easy for me to understand things using above mentioned terms.
Nothing strange here. V8 compiles JavaScript directly into machine code. As a result, unreachable code, such as function b, is removed when it is never referenced. This is a common property of almost every compiler.
What am i missing ?? Is my concepts wrong ?? Is it because of Chrome console ?? Can you explain this behavior ??
In this code snippet, which is different than the specific example of case-1, namely in that the call to b has been removed, the b function has been removed by the compiler. As a result, you do not see any reference to it in the debugger.
case-2
In your examination of case-2, you overlook the fact that the debugger is stopped in the wrong place to analyze the interior scope of function a. As a result, you see a in the debugging window and that is it.
Your understanding section
JS interpreter on reaching line 9 which commands to execute function a(); will create a new execution context for function a (or we can say allocate memory in heap for execution context which is an object and point this to it, right ??)
Not entirely.
line 9: execute function a() [correct]
create an execution context for function a [correct]
allocate memory in heap [incorrect]
execution context is an object [correct]
point this to it [incorrect]
The execution context is an object, however, the compiled function is a static function frame stored on the stack. The this binding is a separate value which does not reference the execution context, but instead provides an entrance for variable scoping.
Now i know that interpreter will first go through the whole function body and will allocate space for variable declarations and function declaration, in the execution context created in heap.
This is incorrect. As noted, the interpreter is working on compiled code. This code already has an established memory footprint. A pointer is created on the heap which points to the compiled code in the stack.
This is evident from the right side of the image where in local Scope we have a reference variable b to the lambda of function.
b is not a lambda function, that would have been var b = () => console.log('Hello i am B');, and would not have been hoisted. That aside, under the hood, a is just a nested context. b is also compiled, and its static reference is just a component of the already compiled a. Scoping and memory storage are two very different concepts.
And now after having a pass through whole function body interpreter will execute code. Now since we already have the function b stored in a's execution context (or a's execution context knows about b),it will execute it. (This is what hoisting is, right ??)
This code is direct, so the interpreter would create a pointer on the heap, and immediately execute the compiled code on the stack. a is executed, then inside of a, b is executed as noted above.
Hoisting is simply moving declarations to the tops of scopes for function declarations and var declarations, but not const or let. Hoisting simply makes your first example equivalent to this:
function a(){
function b(){
console.log('Hello i am B')
}
console.log('Heloo')
b()
}
a()

what is the lifetime of javascript anonymous function?

If I write this in global scope:
(function(){})();
is the anonymous function created when the statement is executed and destroyed immediately after the statement is executed?
if I write this in a function:
function foo()
{
var a=1;
(function(){})();
a++;
}
Does the anonymous function exist until foo returns, or just exist during the execution of that statement?
In this particular case, most engines will optimize that function entirely away, because it does not do anything.
But let's assume that function contains code and is indeed executed. In this case, the function will exist all the time, either as compiled code, as bytecode or as AST for the interpreter.
The part that won't exist all the time is the scope and the possible created closure. The scope created for that function and the closure will only exist as long as the function is executed or a reference to the function with a specific bound scope/closure exists.
So the combination function reference + scope will be allocated at the time the statement (function(){})(); is executed, and can be released after that statement. But the compiled version of function(){} might still exist in memory for later use.
For engines that do just in time compiling and optimization, a function might even exist in different compiled versions.
The JIT+optimizer part of modern js engines is a complex topic, a rough description of v8 can be found here html5rocks: JavaScript Compilation:
In V8, the Full compiler runs on all code, and starts executing code as soon as possible, quickly generating good but not great code. This compiler assumes almost nothing about types at compilation time - it expects that types of variables can and will change at runtime.
In parallel with the full compiler, V8 re-compiles "hot" functions (that is, functions that are run many times) with an optimizing compiler. [...] In the optimizing compiler, operations get speculatively inlined (directly placed where they are called). This speeds execution (at the cost of memory footprint), but also enables other optimizations.
Therefore it may be that the generated code has hardly any similarities to the original one.
So a immediately-invoked function expression might even be completely optimized away using inlining.
If I write this in global scope:
(function(){})();
is the anonymous function created when the statement is executed and destroyed immediately after the statement is executed?
As t.niese said, odds are the engine will optimize that function away entirely. So let's assume it has some code in it:
// At global scope
(function(){ console.log("Hi there"); })();
The engine can't guarantee that that code won't throw an error (for instance, if you replaced console with something else), so I'm fairly sure it can't just inline that.
Now the answer is: It depends.
From a language/specification level, all code in a compilation unit (roughly: script) is parsed when the compilation unit is first loaded. Then, that function is created when the code reaches it in step-by-step execution, executed after being created (which involves creating an execution context for the call), and immediately eligible for garbage collection when done (along with the execution context) because nothing has a reference to it. But that's just theory/high-level specification.
From a JavaScript engine perspective:
The function is parsed before any code runs. The result of that parsing (bytecode or machine code) will be associated with that function expression. This doesn't wait for execution to reach the function, it's done early (in the background on V8 [Google's engine in Chrome and Node.js]).
Once the function has been executed and nothing else can refer to it:
The function object and the execution context associated with calling it are both eligible for GC. When and how that happens depends on the JavaScript engine.
Which leaves the function's underlying code, either bytecode (modern versions of V8 using Ignition, possibly others) or compiled machine code (somehow the function got used so much it got compiled for TurboFan, or older versions of V8 using Full-codegen, others). Whether the JavaScript engine can then throw away that bytecode or machine code will depend on the engine. I doubt engines throw away byte/machine code they've generated for a function if they may need it again (e.g., for a new anonymous function created by a new call to foo). If foo became unreachable, maybe foo's byte/machine code and the anonymous function's could be tossed as unnecessary. I have no idea whether engines do that. On the one hand, it seems like low-hanging fruit; on the other, it seems like something that would be so uncommon it's not worth bothering with. (Remember, here we're not talking about code attached to a function instance, but the code that has been produced from the source that gets attached to an instance when the instance is created, and may get attached to multiple instances over time.)
Here are a couple of articles on the V8 blog that make interesting reading:
26 March 2018: Background compilation
15 May 2017: Launching Ignition and TurboFan
23 August 2016: Firing up the Ignition interpreter (some information outdated and updated by the May 2017 article)
Ignition (some of the Ignition information appears to be slightly out of date relative to the May 2017 article above)
if I write this in a function:
function foo()
{
var a=1;
(function(){})();
a++;
}
Does the anonymous function exist until foo returns, or just exist during the execution of that statement?
Let's assume again there's a console.log in that function, and that I'm correct (it is an assumption on my part) that the fact it relies on a writable global (console) means it can't just be inlined.
The high-level/specification answer is the same: The function is parsed when the script is loaded, created when it's reached, executed, and eligible for GC when it's done executing. But again, that's just high-level concept.
Things are probably different at the engine level:
The code will be parsed before any code in the script runs.
Bytecode or machine code is likely generated before any code in the script runs, although I seem to recall something from the V8 blog about parsing but not immediately compiling the contents of top-level functions. I can't find that article, though, if it wasn't just in my head.
When execution reaches the function, a function object for it is created along with an execution context (unless the engine is sure it can optimize that away without it being observable in code).
Once execution ends, the function object and that execution context are eligible for GC. (They may well have been on the stack, making GC trivial when foo returns.)
The underlying code, though, sticks around in memory in order to be used again (and if used often enough, optimized).

Strategy for JavaScript interpreter implementation (functions) -- am I making sense?

I'm writing a js-to-js interpreter (that is, a Javascript program that takes a Javascript program as an argument and executes it). I'm not trained in compiler theory, I'm just faking it. The expression-evaluation machine is working (using a kind of clunky operator-precedence algorithm), but not yet for functions. So here's my question.
The way I'm thinking of implementing functions looks something like this: When a function is invoked, I'll create a namespace / context for it, also allowing access to the namespaces of enclosing functions and the global namespace.
I'm not yet implementing closures, but these namespaces are designed to work for them. Basically, as I understand it, closures are just the way Javascript refuses to forget the context of a function when it hasn't forgotten the variable which holds the function.
So, when the function is invoked, I'll pass into its context object a copy of the statement which invokes it, along with a pointer to the expression that triggered the function call. Each expression in that statement that has been evaluated already will remember its value. When we return from the function, that statement becomes the current statement, and I start to execute it again -- but I don't re-evaluate expressions that have already been evaluated, including the function just completed. So then I go merrily along with the rest of the statement, potentially calling more functions, etc.
Each statement, expression, and function has an abstract representation built during parsing. During execution, only the current statement has any actual existence, aside from that abstract representation, because really all I need to remember at any given time is:
variables in the current context
variables in enclosing contexts (that is, the most recent invocation of a function -- including the global context -- which encloses the current function)
the current statement
what statement is next
what blocks I'm inside of (just so I know what to do when I hit
the end of one)
the call stack, which is a stack of contexts including variables and the
statement that triggered the call, with its expressions.
A pointer to the specific expression to update with return value from the function / context.
So am I making sense? Thanks for your help!
What you're describing is basically what an interpreter does, yes, but I'd still strongly recommend rethinking your approach. Interpreting Javascript in Javascript is going to run extremely slowly as soon as you're doing anything more complex than adding numbers. Is there some reason you can't separate your debugger from actual execution? If that's not possible, I'd really suggest doing your interpreter in a plug-in or something that gives you lower level speed. Or consider mod'ing something like this: https://developers.google.com/blockly/installation/js-interpreter?hl=en

Does a browser truly read JavaScript line by line OR does it make multiple passes?

I understand that JavaScript is interpreted and not compiled. No problem there. However, I keep reading here that JavaScript is executed "on the fly" and that lines are read one at a time. This idea is confusing me quite a bit when it comes to the following example:
writeToConsole();
function writeToConsole() {
console.log("This line was reached.");
}
For the record, this bit of code will write to the console just fine. Still, how would the browser know of the existence of exampleFunction() if it had not yet reached the function?
In other words, when exactly is this function first interpreted?
First, you make an incorrect assumption: modern JavaScript is compiled. Engines like V8, SpiderMonkey, and Nitro compile JS source into the native machine code of the host platform.
Even in older engines, JavaScript isn't interpreted. They transform source code into bytecode, which the engine's virtual machine executes.
This is actually how things in Java and .NET languages work: When you "compile" your application, you're actually transforming source code into the platform's bytecode, Java bytecode and CIL respectively. Then at runtime, a JIT compiler compiles the bytecode into machine code.
Only very old and simplistic JS engines actually interpret the JavaScript source code, because interpretation is very slow.
So how does JS compilation work? In the first phase, the source text is transformed into an abstract syntax tree (AST), a data structure that represents your code in a format that machines can deal with. Conceptually, this is much like how HTML text is transformed into its DOM representation, which is what your code actually works with.
In order to generate an AST, the engine must deal with an input of raw bytes. This is typically done by a lexical analyzer. The lexer does not really read the file "line-by-line"; rather it reads byte-by-byte, using the rules of the language's syntax to convert the source text into tokens. The lexer then passes the stream of tokens to a parser, which is what actually builds the AST. The parser verifies that the tokens form a valid sequence.
You should now be able to see plainly why a syntax error prevents your code from working at all. If unexpected characters appear in your source text, the engine cannot generate a complete AST, and it cannot move on to the next phase.
Once an engine has an AST:
An interpreter might simply begin executing the instructions directly from the AST. This is very slow.
A JS VM implementation uses the AST to generate bytecode, then begins executing the bytecode.
A compiler uses the AST to generate machine code, which the CPU executes.
So you should now be able to see that at minimum, JS execution happens in two phases.
However, the phases of execution really have no impact on why your example works. It works because of the rules that define how JavaScript programs are to be evaluated and executed. The rules could just as easily be written in a way such that your example would not work, with no impact on how the engine itself actually interprets/compiles source code.
Specifically, JavaScript has a feature commonly known as hoisting. In order to understand hoisting, you must understand the difference between a function declaration and a function expression.
Simply, a function declaration is when you declare a new function that will be called elsewhere:
function foo() {
}
A function expression is when you use the function keyword in any place that expects an expression, such as variable assignment or in an argument:
var foo = function() { };
$.get('/something', function() { /* callback */ });
JavaScript mandates that function declarations (the first type) be assigned to variable names at the beginning of an execution context, regardless of where the declaration appears in source text (of the context). An execution context is roughly equatable to scope – in plain terms, the code inside a function, or the very top of your script if not inside a function.
This can lead to very curious behavior:
var foo = function() { console.log('bar'); };
function foo() { console.log('baz'); }
foo();
What would you expect to be logged to the console? If you simply read the code linearly, you might think baz. However, it will actually log bar, because the declaration of foo is hoisted above the expression that assigns to foo.
So to conclude:
JS source code is never "read" line-by-line.
JS source code is actually compiled (in the true sense of the word) in modern browsers.
Engines compile code in multiple passes.
The behavior is your example is a byproduct of the rules of the JavaScript language, not how it is compiled or interpreted.
All functions will be examined first by the browser before any code is executed.
However,
var foo = function(){};
This will not be examined, and thus the following will throw a TypeError: undefined is not a function
foo();
var foo = function(){};
It does take 2 passes. The first pass parses the syntax tree, a part of which is performing hoisting. That hoisting is what makes your posted code work. Hoisting moves any var or named function declarations function fn(){} (but not function expressions fn = function(){}) to the top of the function they appear in.
The second pass executes the parsed, hoisted, and in some engines compiled, source code tree.
Check out this example. It shows how a syntax error can prevent all execution of your script by throwing a wrench in the first pass, which prevents the second pass (actual code execution) from ever happening.
var validCode = function() {
alert('valid code ran!');
};
validCode();
// on purpose syntax error after valid code that could run
syntax(Error(
http://jsfiddle.net/Z86rj/
No alert() occurs here. The first pass parsing fails, and no code executes.
The script is first parsed, then interpreted, and then executed. When the first statement (writeToConsole();) is executed, the function declaration has already been interpreted.
Since all variable and function declarations are hoisted in the current scope (in your case, the global script scope), you will be able to call a function that was declared below.
JavaScript is actually interpreted line by line. BUT, before it's executed, there is a first pass made by the compiler, reading certain things in (pretty geeky, have a look at this: https://www.youtube.com/watch?v=UJPdhx5zTaw if you're really interested).
The point is, JavaScript will be first "read" by the compiler, who stores functions defined as function foo(){...} already. You can call those ones at any given time in the script, given you are calling them from the same or a subordinate scope. What modern compilers also do is preallocate objects, so as a side effect it does make sense to strongly type your variables for the matter of performance.
var foo = function(){...} will not be stored by the compiler, due to the fact that JavaScript is loosely typed and the type of a variable could change during execution time.
The javascript engine create a execution context before executing your code. The execution context is created mainly in two phases:
Creation phase
Excecution phase
Creation Phase
In the creation phase we have the Global object, this and outer environment reference.In the creation phase as the parser runs through the code and begins to setup what we have written for translation, it recognizes where we have created variables and where we have created function. Basically it setup memory space for variable and functions Hoisting.
Execution Phase
In this the code is run line by line(interpreting, converting, compiling and executing it on the computer).
consider the following example, in this we are able to call the function b even before its declaration. This is because the javascript engine already knows the existence of the function b. And this is also referred to as hoisting in javascript.
b();
function b() {
console.log("I have been hoisted");
}

Categories

Resources