Original sentence: Https://Wangdoc.Com/javascript/index.Html
Browser Environment Overview
JavaScript is a scripting language built-in browser. In other words, the browser built JavaScript engine, and provides a variety of interfaces, allowing JavaScript script can control various functions of the browser. Once the Web page embedded JavaScript scripts, browser loads the page, it will go to execute the script, so as to achieve the purpose of operating a browser, to achieve a variety of dynamic performance of your pages.
This chapter describes the various start a JavaScript interface provided by the browser. Firstly, the method of JavaScript code embedded in Web pages.
The method of code embedded in the webpage
JavaScript code embedded in Web pages, there are three main methods.
<script>
Element directly embedded code.<script>
Tag loading external script- Event Properties
- URL protocol
script elements embedded code
<script>
Internal elements can directly write JavaScript code.
<script>
var x = 1 + 5;
console.log(x);
</script>
<script>
There is a label type
attribute that specifies the type of script. For JavaScript script, the type
property can be set to two kinds of value.
text/javascript
: This is the default value, but also the value of history has always been set. If you omit thetype
property, this is the default value. For older browsers, set this value better.application/javascript
: For newer browsers, set to the recommended value.
<script type="application/javascript">
console.log('Hello World');
</script>
Since the <script>
label is the default JavaScript code. Therefore, when the embedded JavaScript script type
attribute can be omitted.
If the type
value of the property, the browser does not recognize, it will not execute the code within. Take advantage of this, you can <script>
embed any text in the label, just add a browser does not recognize the type
attribute.
<script id="mydata" type="x-custom-data">
console.log('Hello World');
</script>
The above code, the browser will not execute, it will not display its contents, because they do not understand its type
properties. However, the <script>
node still exists in the DOM, you can use <script>
the node text
attribute read its contents.
document.getElementById('mydata').text
// console.log('Hello World');
script element loading external script
<script>
Tags can also load external script file specified.
<script src="https://www.example.com/script.js"></script>
If the script file using non-English characters, you should also indicate the character encoding.
<script charset="utf-8" src="https://www.example.com/script.js"></script>
Script loaded must be pure JavaScript code, can not have HTML
the code and <script>
labels.
Loading external scripts and code blocks directly added, both methods can not be mixed. The following code console.log
statements directly ignored.
<script charset="utf-8" src="example.js">
console.log('Hello World!');
</script>
To prevent attackers from tampering with external script script
tag allows you to set a integrity
property, write to the external script Hash signature is used to verify the consistency of the script.
<script src="/assets/application.js"
integrity="sha256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs=">
</script>
The above code, script
the label has an integrity
attribute that specifies the external script /assets/application.js
SHA256 signature. Once the script was changed, resulting SHA256 signatures do not match, the browser will refuse to load.
Event Properties
Event properties (such as page elements onclick
and onmouseover
), you can write JavaScript code. When the specified event occurs, it will call the code.
<button id="myBtn" onclick="console.log(this.id)">点击</button>
The above event property code, only one statement. If there are multiple statements, separated by semicolons can be.
URL protocol
URL support javascript:
agreement that the code is written in the position of the URL, when using this URL will execute JavaScript code.
<a href="javascript:console.log('Hello')">点击</a>
The address bar of the browser can also perform javascript:
protocol. Will be javascript:console.log('Hello')
put in the address bar, press the Enter key will execute the code.
If the JavaScript code returns a string, the browser will create a new document, display the contents of the string, the original content of the document will disappear.
<a href="javascript: new Date().toLocaleTimeString();">点击</a>
The above code, after the user clicks on the link will open a new document, which has the current time.
If the return is not a string, then the browser will not create a new document, it will not jump.
<a href="javascript: console.log(new Date().toLocaleTimeString())">点击</a>
The above code, the user clicks the link, the page will not jump, it will only display the current time in the console.
javascript:
A common use of the protocol is to bookmark script Bookmarklet. Because of saved bookmarks browser is a URL, so javascript:
when the URL can also be saved on the inside, the user selects this bookmark will execute the script on the current page. To prevent bookmarks replace the current document, you can add a script before void
, or finally add in the script void 0
.
<a href="javascript: void new Date().toLocaleTimeString();">点击</a>
<a href="javascript: new Date().toLocaleTimeString();void 0;">点击</a>
Both the above wording, click on the link, the code will not execute a jump page.
script elements
working principle
JavaScript enabled browser, mainly through the <script>
elements to complete. Normal page load process is like this.
- HTML web browser while downloading, while start parsing. In other words, do not wait until the download finished, they begin to resolve.
- Resolution process, the browser sees
<script>
elements on the suspension resolution, the control of page rendering forwarded to the JavaScript engine. - If the
<script>
element references external scripts, download the script and then execute, or to execute code directly. - JavaScript engine is finished, control is returned to the rendering engine, resume parsing HTML pages down.
When loading external script, the browser page rendering pauses, waiting for the script to download and execution is completed, and then continue rendering. The reason is that JavaScript code can modify the DOM, it is necessary to give it the right to control, otherwise it will lead to complicated problems thread contest.
If the external script load time is very long (have not been able to complete the download), then the browser will have to wait for the download is complete script, resulting in prolonged loss of response page, the browser will show "suspended animation" state, which is called "blocking effect" .
To avoid this, it is good practice to <script>
label are placed in the bottom of the page, rather than the head. So even in the face unresponsive script, the main web page rendering has been completed, the user can see at least content, rather than face a blank page. If some script code is very important, must be placed in the page header, the best code is written directly to the page instead of connecting an external script file, which can shorten the loading time.
Script files are placed in the tail of the page to load, there is a benefit. Because before you call DOM DOM node structure generation, JavaScript will complain if the script on the page to load the tail, there is no problem, because when the DOM certainly has been generated.
<head>
<script>
console.log(document.body.innerHTML);
</script>
</head>
<body>
</body>
When the above code will execute error, because the document.body
element has not been generated.
One solution is to set DOMContentLoaded
an event callback function.
<head>
<script>
document.addEventListener(
'DOMContentLoaded',
function (event) {
console.log(document.body.innerHTML);
}
);
</script>
</head>
The above code, designated DOMContentLoaded
after the incident, began to execute the code. DOMContentLoaded
The event will only be triggered after the DOM structure generation.
Another solution is to use <script>
the label onload
attribute. When the <script>
label specified external script file downloading and parsing is complete, will trigger an load
event, you can put the code you need to perform, in the event of a callback function inside.
<script src="jquery.min.js" onload="console.log(document.body.innerHTML)">
</script>
However, if the script at the bottom of the page, you can completely normal way to write the above two methods are not needed.
<body>
<!-- 其他代码 -->
<script>
console.log(document.body.innerHTML);
</script>
</body>
If there are multiple script
tags, such as follows.
<script src="a.js"></script>
<script src="b.js"></script>
The browser will download in parallel a.js
and b.js
, however, will ensure the implementation of the first execution a.js
, and then executed b.js
, even if the latter before the download is complete, as well. In other words, the script execution order is determined by the order in which they appear on the page, which is to ensure that the dependencies between the scripts do not be undermined. Of course, these two scripts will have to load "blocking effect" must wait until they are loaded, the browser will continue rendering the page.
Parse and execute CSS, will produce obstruction. Firefox browser will wait until the previous script all stylesheets are downloaded and parsed finished, and then execute the script; Webkit is the script references the style once found, it will suspend the script, download and parse the style sheet until completion, then resumes.
In addition, resources from the same domain name, such as script files, style sheets files, image files and other browsers generally limited, and download up 6 to 20 resources, that is up to at the same time open TCP connections is limited, which is to prevent too much stress on the server. If the resource is from a different domain name, you do not have this limitation. So, usually under static files in a different domain, in order to speed up the download speed.
defer property
In order to solve the problems blocking script file download page rendering, a method is <script>
adding elements defer
property. Its role is to delay execution of the script, to wait until the DOM is generated, and then execute the script.
<script src="a.js" defer></script>
<script src="b.js" defer></script>
The above code, only to wait until after the DOM is ready, will be performed a.js
and b.js
.
defer
Running process properties as follows.
- Browser start parsing an HTML page.
- Parsing process, it was found with the
defer
attributes of<script>
the element. - Continue down the browser parses HTML pages while downloading a parallel
<script>
external script elements loaded. - The browser has finished parsing an HTML page, then go back and execute the script has finished downloading.
With defer
property, the browser to download a script file, do not block page rendering. Download the script file DOMContentLoaded
before executing event-triggered (ie just finished reading the </html>
label), and can guarantee the order of execution of the order that they appear on the page.
For built instead of loading an external script script
tags, and dynamically generated script
label defer
property does not work. In addition, the use of defer
an external script loads should not use the document.write
method.
async attribute
Another way to solve the "blocking effect" is <script>
an element added async
attributes.
<script src="a.js" async></script>
<script src="b.js" async></script>
async
The role attribute is used by another process to download the script, do not block rendering download.
- Browser start parsing an HTML page.
- Parsing process found with
async
attributescript
tags. - Continue down the browser parses HTML pages while downloading a parallel
<script>
external script tag. - Script download is complete, the browser Pause parse HTML pages, start the download scripts.
- The script is finished, the browser resume parsing HTML pages.
async
Properties can be downloaded at the same time to ensure the script, the browser continues to play. It should be noted that once the use of this property, we can not guarantee the order of execution of the script. Which script to download the end, it is the first implementation of that script. In addition, async
the properties of the script file inside the code, should not use document.write
the method.
defer
Property and async
property in the end which one to use?
Generally speaking, if no dependencies between the scripts, use async
property, if there are dependencies between scripts, use the defer
property. If you use async
and defer
property, the latter does not work, the browser behavior by the async
decision attribute.
Dynamically loaded script
<script>
Elements can also be dynamically generated, generates and then insert a page, in order to achieve dynamic loading script.
['a.js', 'b.js'].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
document.head.appendChild(script);
});
The benefit of this approach is that dynamically generated script
label does not block page rendering, it will not cause the browser suspended animation. But the problem is that this method does not guarantee the order of execution of the script, which script file before the download is complete, it is executed first.
If you want to avoid this problem, you can set the async property false
.
['a.js', 'b.js'].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
The above code does not block the page rendering, but also to ensure that b.js
in a.js
the implementation of the back. But note that this code is loaded in the back of the script file, so they have to wait for b.js
execution to complete before execution.
If you want to specify a callback function for the script dynamically loaded, you can use the following wording.
function loadScript(src, done) {
var js = document.createElement('script');
js.src = src;
js.onload = function() {
done();
};
js.onerror = function() {
done(new Error('Failed to load script ' + src));
};
document.head.appendChild(js);
}
Load protocol used
If you do not specify the protocol, the browser's default download using HTTP protocol.
<script src="example.js"></script>
The above example.js
default is to use the HTTP protocol to download, if you want to download using the HTTPS protocol, you must specify the.
<script src="https://example.js"></script>
But sometimes we will want to determine the loading protocol agreement based on the page itself, then the following wording can be used.
<script src="//example.js"></script>
The composition of the browser
The core browser is two parts: the rendering engine and JavaScript interpreter (also known as JavaScript engine).
Rendering engine
The main effect of rendering engine that the web page code is rendered as flat documents the user can visually perceptible.
Different browsers have different rendering engine.
- Firefox: Gecko engine
- Safari: WebKit 引擎
- Chrome: Blink engine
- IE: Trident engine
- Edge: EdgeHTML 引擎
Web page rendering engine process, usually divided into four stages.
- Parsing code: HTML Code resolves to DOM, CSS code analysis is CSSOM (CSS Object Model).
- Object Synthesis: DOM and rendering CSSOM synthesis of a tree (render tree).
- Layout: render tree calculated layout (layout).
- Draw: The render tree drawn to the screen.
More than four steps are not strictly sequential execution, often the first step is not yet complete, second and third step has already begun. So, we will see this situation: the page's HTML code is not downloaded, but the browser has shown the content.
Heavy flow and redraw
Render tree into a page layout, known as the "layout flow" (flow); the layout of the page is displayed in this process, known as the "draw" (paint). They have a blocking effect, and will spend a lot of time and computing resources.
After page generation, scripts and stylesheets operation operation will trigger a "heavy flow" (reflow) and "redraw" (repaint). User interaction will trigger heavy flow and redrawn, such as setting up mouseover ( a:hover
) effects, scrolling page, enter text input box, change the window size, and so on.
And redraw the heavy flow does not necessarily occur together, will inevitably lead to heavy flow redraw, you do not necessarily need to redraw the heavy flow. Such as changing the color elements, it will only lead to redraw without causing heavy flow; change the layout elements, and will lead to redraw heavy flow.
In most cases, the browser determines intelligence, and the heavy stream redraw limited only to the relevant subtree above, minimizing cost price, without regenerated global page.
As a developer, you should try to reduce the number and cost of trying to redraw. For example, try not to change the top of DOM elements, and to changes in the underlying DOM elements in place; another example, redraw table
the layout and flex
layout, the cost will be relatively large.
var foo = document.getElementById('foobar');
foo.style.color = 'blue';
foo.style.marginTop = '30px';
The above code will only lead to a redrawing because the browser DOM changes accumulate, then a one-time execution.
Here are some optimization techniques.
- DOM DOM to read or write, try to write together, do not mix. Do not read a DOM node, then write immediately, followed by reading a DOM node.
- DOM cache information.
- Do one by one to change the style, but the use of one-time change CSS class style.
- Use
documentFragment
manipulate DOM - Animation using
absolute
positioning orfixed
location, so the impact on other elements can be reduced. - Show hidden element only when necessary.
- Use
window.requestAnimationFrame()
, because it can postpone the execution of the code when the re-flow to the next, rather than immediately required page heavy flow. - Using Virtual DOM (virtual DOM) library.
The following is an window.requestAnimationFrame()
example of the contrast effect.
// 重绘代价高
function doubleHeight(element) {
var currentHeight = element.clientHeight;
element.style.height = (currentHeight * 2) + 'px';
}
all_my_elements.forEach(doubleHeight);
// 重绘代价低
function doubleHeight(element) {
var currentHeight = element.clientHeight;
window.requestAnimationFrame(function () {
element.style.height = (currentHeight * 2) + 'px';
});
}
all_my_elements.forEach(doubleHeight);
The above first code, read each time the DOM, is written the new value will cause rearrangement and stop heavy flow. The second paragraph of the code to all writes are accumulated together to change the code on the cost of DOM is minimized.
JavaScript engine
The main role of the JavaScript engine that reads web pages JavaScript code to run after their treatment.
JavaScript is an interpreted language, which means it does not need to compile, run by an interpreter in real time. The advantage is that the operation and modifications are more convenient, you can refresh the page reinterpretation; drawback is that each run should call the interpreter, larger overhead, run slower than a compiled language.
In order to improve the speed, current browsers will to some extent JavaScript compiler generates bytecode similar (bytecode The) of the intermediate code to improve the operating speed.
Early on, the process of internal browser JavaScript is as follows:
- Read the code, a lexical analysis (Lexical analysis), the element code into word (token).
- Parsing of the word yuan (parsing), the code is organized into "syntax tree" (syntax tree).
- Use "translator" (translator), code into byte code (bytecode).
- Use "bytecode interpreter" (bytecode interpreter), the byte code into machine code.
Progressive interpretation of the bytecode into machine code, is very inefficient. In order to improve the speed, modern browser to a "time compiler" (Just In Time compiler, the JIT abbreviation), i.e., only bytecode compiler at run time, using a line where the line on which the compiler, the compiler and cache the results ( inline cache). Normally, the compiler program is the result of a frequently used, only a small part of the code, with the cache, runs the entire program will be significantly improved.
Byte code can not be run directly, but runs on a VM (Virtual Machine), generally known as virtual machine JavaScript engine. Not all have JavaScript virtual machine is running bytecode, and some JavaScript virtual machine based on the source code, that is as long as possible, by JIT (just in time) compiler to compile source code directly into machine code to run, omitted bytecode step. This is not the same with other languages using a virtual machine (such as Java) are. The aim is to optimize the code as much as possible, to improve performance. The following are some of the most common JavaScript virtual machine:
- Chakra (Microsoft Internet Explorer)
- Nitro/JavaScript Core (Safari)
- How (Opera)
- SpiderMonkey (Firefox)
- V8 (Chrome, Chromium)
Reference links
- John Dalziel, The race for speed part 2: How JavaScript compilers work
- Jake Archibald, Deep dive into the murky waters of script loading
- Mozilla Developer Network, window.setTimeout
- Remy Sharp, Throttling function calls
- Ayman Farhat, An alternative to JavaScript's evil setInterval
- Ilya Grigorik, Script-injected "async scripts" considered harmful
- Axel Rauschmayer, ECMAScript 6 promises (1/2): foundations
- Daniel Imms, async vs defer attributes
- Craig Buckler, Load Non-blocking JavaScript with HTML5 Async and Defer
- Domenico De Felice, How browsers work