functionbigNumberAdd(a, b) { const maxLength = Math.max(a.length, b.length); a = a.padStart(maxLength, '0'); b = b.padStart(maxLength, '0');
let result = ''; let carry = 0;
for (let i = maxLength - 1; i >= 0; i--) { const sum = Number(a[i]) + Number(b[i]) + carry; // This is string concatenation, not numeric addition. result = (sum % 10) + result; // if sum > 10, we only need the last digit. carry = Math.floor(sum / 10); // the carry is the first digit when sum > 10. }
// Don't forget the last carry. if (carry > 0) { result = carry + result; }
Posted onEdited onInhttp Symbols count in article: 146Reading time ≈1 mins.
Introduction
HTTP has two types of messages, request message and response message. Both messages consist of a start line, headers, and an optional body.
Note that, HTTP messages, as defined in HTTP/1.1 and earlier, are human-readable. In HTTP/2, these messages are embedded into a binary structure, a frame, allowing optimizations like compression of headers and multiplexing.
Request Message
Http Request message consists of the following elements:
An HTTP method.
The path of the resource to fetch.
The version of the HTTP protocol.
Optional headers.
An optional body.
Response Message
Http Response message consists of the following elements:
The version of the HTTP protocol.
A status code indicating the success or failure of the request.
Posted onEdited onInhttp Symbols count in article: 727Reading time ≈3 mins.
The version history of HTTP
Version
Year introduced
Current status
Usage in August 2024
Support in August 2024
HTTP/0.9
1991
Obsolete
0
100%
HTTP/1.0
1996
Obsolete
0
100%
HTTP/1.1
1997
Standard
33.8%
100%
HTTP/2
2015
Standard
35.3%
66.2%
HTTP/3
2022
Standard
30.9%
30.9%
HTTP/0.9
HTTP/0.9 is the first version of the HTTP protocol. It was a simple protocol that allowed clients to request a file from a server. The server would then send the file back to the client. The protocol did not support headers or status codes, and the client and server communicated using plain text.
HTTP/1.0
HTTP/1.0 was released in 1996 and introduced several new features to the protocol. These features included support for headers, status codes, and the ability to send multiple files in a single request. HTTP/1.0 also introduced the concept of persistent connections, which allowed clients to reuse a single connection to send multiple requests.
HTTP/1.1
HTTP/1.1 was released in 1999 and is the most widely used version of the HTTP protocol today. It introduced several new features, including support for chunked transfer encoding, which allows servers to send data in chunks, and the ability to reuse connections for multiple requests. HTTP/1.1 also introduced several new status codes, such as 100 Continue and 206 Partial Content.
Details about HTTP/1.1:
HTTP/1.1 is a text-based protocol.
HTTP/2
HTTP/2 was released in 2015 and introduced several new features to the protocol. These features included support for multiplexing, which allows clients to send multiple requests over a single connection, and server push, which allows servers to send resources to clients before they are requested. HTTP/2 also introduced several new status codes, such as 103 Early Hints and 421 Misdirected Request.
Details about HTTP/2:
HTTP/2 Message is binary, instead of textual.
HTTP/3
HTTP/3 is the latest version of the HTTP protocol and is currently in development. It is based on the QUIC protocol, which is a new transport protocol that is designed to improve the performance of web applications. HTTP/3 introduces several new features, including support for multiplexing, which allows clients to send multiple requests over a single connection, and server push, which allows servers to send resources to clients before they are requested. HTTP/3 also introduces several new status codes, such as 103 Early Hints and 421 Misdirected Request.
当客户端再次请求资源时,会将上次请求时服务器返回的Last-Modified值放在请求头中的If-Modified-Since字段中,服务器会根据这个值判断资源是否发生了变化。如果资源没有发生变化,服务器会返回304 Not Modified状态码,表示资源没有发生变化,客户端可以使用缓存。
ETag
ETag是一个HTTP响应头部字段,用于指定资源的唯一标识。它的值是一个字符串。服务器会根据资源的内容生成一个唯一的字符串(注意,生成算法因服务器而异),然后将这个字符串作为ETag的值。当客户端再次请求资源时,会将上次请求时服务器返回的ETag值放在请求头中的If-None-Match字段中,服务器会根据这个值判断资源是否发生了变化。如果资源没有发生变化,服务器会返回304 Not Modified状态码,表示资源没有发生变化,客户端可以使用缓存。
console.log(name); // undefined var name = 'Philip';
以上代码等价于:
1 2 3
var name; // `var`声明的变量会被提升到其作用域顶部。 console.log(name); // undefined name = 'Philip';
如果var是在函数作用域声明的,那么它会被提升到函数作用域的顶部。
1 2 3 4 5
functionprintName() { console.log(name); // undefined var name = 'Philip'; } printName();
以上代码等价于:
1 2 3 4 5 6
functionprintName() { var name; // `var`声明的变量会被提升到其作用域顶部。 console.log(name); // undefined name = 'Philip'; } printName();
let和const声明的变量不会被提升。
对于let和const,它们不会被提升,所以下面代码会报错。
1 2
console.log(num); // ReferenceError: Cannot access 'num' before initialization const num = 1;
前面说过,关于let和const是否被提升有争议。
一种说法是let和const不会被提升,所以在声明之前访问会报错。
另一种说法是let和const会被提升,但是在声明之前访问会抛出Temporal Dead Zone错误。
比如下面的代码:
1 2 3 4 5
const x = 1; { console.log(x); // ReferenceError: Cannot access 'x' before initialization const x = 2; }
这段代码会报错,但是如果我们把{}内的const x = 2;注释掉,那么代码就不会报错。如果const x = 2没有被提升的话,那么console.log(x)应该可以访问到全局的const x = 1,而不会报错。换句话说:因为const x = 2被提升了,所以console.log(x)访问的是提升后的x,而此时x还没有被初始化,所以报错。
functionfoo() { var a; // value of a is `undefined` if (a) { a = 10; // never executed. } console.log(a); }
foo();
第三题
1 2 3 4 5 6 7 8 9 10 11 12
functionfn() { console.log(typeof foo); var foo = 'variable';
functionfoo() { return'function'; }
console.log(typeof foo); }
fn();
还是那句话,此类题目的解法就是按照提升规则把代码重新写一遍,以上代码提升后等价于如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
functionfn() { var foo;
functionfoo() { return'function'; }
console.log(typeof foo); foo = 'variable';
console.log(typeof foo); }
fn();
所以输出结果是function和string。
变量的作用域
var声明的变量有只两种作用域:全局作用域和函数作用域。(没有块级作用域)
let和const声明的变量有三种作用域:全局作用域,函数作用域和块级作用域。
var声明的全局变量会挂载到window对象上,而let和const不会。
let和const有临时性死区,而var没有。
面试题
第一题
以下代码输出什么?
1 2 3 4 5 6
let x = 1; { let x = 2; }
console.log(x);
答案:1,因为let有块级作用域,所以let x = 2只在{}内有效。
第二题
以下代码输出什么?
1 2 3 4 5 6
var x = 1; { var x = 2; }
console.log(x);
答案:2,因为var没有块级作用域,所以var x = 2会覆盖外部的var x = 1。
第三题
以下代码输出什么?
1 2 3 4 5
let name = 'zdd'; { console.log(name); let name = 'Philip'; }
答案:ReferenceError: Cannot access ‘name’ before initialization。因为let有块级作用域,所以console.log(name);访问的是let name = 'Philip';之前的name,而此时name还没有被初始化,处于暂时性死区中,所以报错。
第四题
以下代码输出什么?
1 2 3 4 5 6 7 8 9
'use strict';
{ functionfoo() { console.log('foo'); } }
foo();
答案:ReferenceError: foo is not defined。因为foo是在块级作用域内声明的,所以在外部无法访问。但是如果我们把'use strict';去掉,那么代码就可以正常运行。因为在非严格模式下,函数声明会被提升到全局作用域。
第五题
以下代码输出什么?
1 2 3 4 5 6 7 8 9 10 11 12 13
(() => { let x; let y; try { thrownewError(); } catch (x) { x = 1; y = 2; console.log(x); } console.log(x); console.log(y); })();
Posted onEdited onIninterview Symbols count in article: 596Reading time ≈2 mins.
Introduction
There is a very famous question, “What happened when you input a URL and press Enter in the browser?”
Answer
1. URL parsing
When you input a URL in the browser, the browser will parse the URL into several parts:
Protocol: http or https
Host/Domain: www.example.com
Port: 80 or 443
Path: /page.html
Query: ?name=Philip
Fragment: #section1
2. DNS lookup
The browser will check the cache to see if the DNS lookup result is cached. If not, it will send a DNS query to the DNS server to get the IP address of the host.
Check browser cache.
Check OS cache.
Check router cache.
Check ISP(Internet Service Provider) cache.
Make request to the DNS server.(Only if all cache above failed!)
3. TCP connection
The browser will establish a TCP connection with the server using the IP address and port number. This including the TCP handshake process. 关于TCP的连接与关闭,可以看这篇
4. HTTP request
The browser will send an HTTP request to the server. The request includes the following information:
The server will process the request and generate a response. The response includes the following information:
Status code: 200, 404, 500, etc.
Response headers: Content-Type, Content-Length, etc.
Response body: HTML, CSS, JavaScript, etc.
Cookies: Set-Cookie header.
6. Browser rendering
The browser will render the response HTML, CSS, and JavaScript to display the web page to the user. When browser parse html page, it may download js file embed in html, this process might block the parsing, see here for details.
Parse HTML: The browser will parse the HTML to create the DOM tree.
The file was transferred from the server to the browser as binary data.
The browser will parse the binary data to the .html file.
The browser constructs the DOM tree based on the parsed HTML.
If the html contains external CSS files, the browser will download the css in parallel, this won’t block the DOM construction.
If the html contains external JavaScript files, the browser will download the js in parallel, this will/won’t block the DOM construction. see here for details.
Parse CSS: The browser will parse the CSS to create the CSSOM tree.
Render tree: The browser will combine the DOM tree and CSSOM tree to create the render tree.
Layout: The browser will calculate the position and size of each element in the render tree.
Paint: The browser will paint the pixels on the screen.
Composite: The browser will composite the layers to display the final web page.
JavaScript execution: The browser will execute the JavaScript code to add interactivity to the web page.
Event handling: The browser will handle user events like click, scroll, etc.
Conclusion
External CSS doesn’t block the DOM construction, but might block the render tree construction since the browser needs to wait for the CSSOM tree to be constructed.
External JavaScript might block the DOM construction if and only if:
The Scripts is in <head> tag, it will block the DOM construction.
And the script doesn’t set async or defer.
If the script is at the end of the <body> tag, it won’t block the DOM construction even when it doesn’t set async or defer.
Posted onEdited onInjavascript Symbols count in article: 353Reading time ≈1 mins.
Introduction
reduce() is a very import method in JavaScript, it executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
Most of the time, reduce() is used to sum up the values in an array, but it can be used for many other things as well.
1 2 3
const nums = [1, 2, 3]; const sum = nums.reduce((a, c) => a + c); console.log(sum);
Why we use a and c for the parameters of the reducer function, because a = accumulator, c = currentValue.
Each call to the reducer produces a new value, and this value is passed to the next call of the reducer as the accumulator(first argument). Otherwise, a will become undefined in the next call.
Note that you must return value from the callbackFn, otherwise the result will be undefined.
1 2 3
const nums = [1, 2, 3]; const sum = nums.reduce((a, c) => {a + c}); // won't work since we didn't return the value console.log(sum); // undefined.
I found this when I working on the following work, group the following inventory by type property: