javascript: Browser Environment Overview

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 typeattribute that specifies the type of script. For JavaScript script, the typeproperty 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 the typeproperty, 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 typeattribute can be omitted.

If the typevalue 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 typeattribute.

<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 typeproperties. However, the <script>node still exists in the DOM, you can use <script>the node textattribute 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 HTMLthe code and <script>labels.

Loading external scripts and code blocks directly added, both methods can not be mixed. The following code console.logstatements directly ignored.

<script charset="utf-8" src="example.js">
  console.log('Hello World!');
</script>

To prevent attackers from tampering with external script scripttag allows you to set a integrityproperty, 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, scriptthe label has an integrityattribute that specifies the external script /assets/application.jsSHA256 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 onclickand 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.

  1. HTML web browser while downloading, while start parsing. In other words, do not wait until the download finished, they begin to resolve.
  2. Resolution process, the browser sees <script>elements on the suspension resolution, the control of page rendering forwarded to the JavaScript engine.
  3. If the <script>element references external scripts, download the script and then execute, or to execute code directly.
  4. 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.bodyelement has not been generated.

One solution is to set DOMContentLoadedan event callback function.

<head>
  <script>
    document.addEventListener(
      'DOMContentLoaded',
      function (event) {
        console.log(document.body.innerHTML);
      }
    );
  </script>
</head>

The above code, designated DOMContentLoadedafter the incident, began to execute the code. DOMContentLoadedThe event will only be triggered after the DOM structure generation.

Another solution is to use <script>the label onloadattribute. When the <script>label specified external script file downloading and parsing is complete, will trigger an loadevent, 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 scripttags, such as follows.

<script src="a.js"></script>
<script src="b.js"></script>

The browser will download in parallel a.jsand 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 deferproperty. 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.jsand b.js.

deferRunning process properties as follows.

  1. Browser start parsing an HTML page.
  2. Parsing process, it was found with the deferattributes of <script>the element.
  3. Continue down the browser parses HTML pages while downloading a parallel <script>external script elements loaded.
  4. The browser has finished parsing an HTML page, then go back and execute the script has finished downloading.

With deferproperty, the browser to download a script file, do not block page rendering. Download the script file DOMContentLoadedbefore 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 scripttags, and dynamically generated scriptlabel deferproperty does not work. In addition, the use of deferan external script loads should not use the document.writemethod.

async attribute

Another way to solve the "blocking effect" is <script>an element added asyncattributes.

<script src="a.js" async></script>
<script src="b.js" async></script>

asyncThe role attribute is used by another process to download the script, do not block rendering download.

  1. Browser start parsing an HTML page.
  2. Parsing process found with asyncattribute scripttags.
  3. Continue down the browser parses HTML pages while downloading a parallel <script>external script tag.
  4. Script download is complete, the browser Pause parse HTML pages, start the download scripts.
  5. The script is finished, the browser resume parsing HTML pages.

asyncProperties 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, asyncthe properties of the script file inside the code, should not use document.writethe method.

deferProperty and asyncproperty in the end which one to use?

Generally speaking, if no dependencies between the scripts, use asyncproperty, if there are dependencies between scripts, use the deferproperty. If you use asyncand deferproperty, the latter does not work, the browser behavior by the asyncdecision 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 scriptlabel 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.jsin a.jsthe 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.jsexecution 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.jsdefault 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.

  1. Parsing code: HTML Code resolves to DOM, CSS code analysis is CSSOM (CSS Object Model).
  2. Object Synthesis: DOM and rendering CSSOM synthesis of a tree (render tree).
  3. Layout: render tree calculated layout (layout).
  4. 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 tablethe layout and flexlayout, 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 documentFragmentmanipulate DOM
  • Animation using absolutepositioning or fixedlocation, 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:

  1. Read the code, a lexical analysis (Lexical analysis), the element code into word (token).
  2. Parsing of the word yuan (parsing), the code is organized into "syntax tree" (syntax tree).
  3. Use "translator" (translator), code into byte code (bytecode).
  4. 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:

Reference links

Guess you like

Origin www.cnblogs.com/wbyixx/p/12499348.html