Modern JavaScript tutorial study notes

This is my notes of learning modern JavaScript tutorials, their content is really good, there is a feeling of regret, at that time if only beginner JS can meet… No plagiarism, just notes, and try to talk about it a little bit, if involved in infringement, will be deleted immediately

Popup window

window.open(' ') // Open a popover
Copy the code

Block pop-up window

window.open() / / stop
button.onclick = () = > window.open() // Yes, popovers are user-triggered events
setTimeout(() = > window.open(), 3000) // Chrome can open popovers
Copy the code
window.open(url, name, params) //url, name: window name, params: configuration string
Copy the code

Access popup window

let newWin = window.open()
newWin.document.write(' ')
Copy the code

Visit window window.opener Visit window window.opener

Close the win.close() win.closed attribute to check whether it is closed

Win.moveby () win.moveto () win.resizeby () win.resizeto () win.onresize event for inside win.scrollby ()

win.scrollTo() elem.scrollIntoView() win.onscroll()

Window.focus () window.blur() focus/blur event

Cross-window communication

Cross-window access is restricted by same-origin not same-origin, we can’t access the content in the window, but we can modify the location

Ifame. ContentWindow Window Ifame. ContentDocument Document

<iframe src="https://example.com" id="iframe"></iframe>

<script>
  iframe.onload = function() {
    // We can get a reference to the inner window
    let iframeWindow = iframe.contentWindow; // OK
    try {
      / /... But the documents are not available
      let doc = iframe.contentDocument; // ERROR
    } catch(e) {
      alert(e); // Security Error (another source)
    }

    // We cannot read the URL of the page in iframe
    try {
      // Cannot read the URL from the location object
      let href = iframe.contentWindow.location.href; // ERROR
    } catch(e) {
      alert(e); // Security Error
    }

    / /... We can ** write ** location (so something else is loaded in the iframe)!
    iframe.contentWindow.location = '/'; // OK

    iframe.onload = null; // Empty the handler and do not run it after the location changes
  };
</script>
Copy the code
<script>
  let oldDoc = iframe.contentDocument; / / error
  iframe.onload = function() {
    let newDoc = iframe.contentDocument;
    // The loaded document is different from the original document!
    alert(oldDoc == newDoc); // false
  };
</script>
Copy the code

So in order to get the document earlier we can do this

let oldDoc = iframe.contentDocument
  let timer = setInterval(() = > {
    let newDoc = iframe.contentDocument
    if (newDoc === oldDoc) return;
    clearInterval(timer)
  }, 100)
Copy the code

Frames [0] window.frames. IframeName (name=’iframeName’)

The Sandbox feature allows you to disable certain behaviors in an IFrame, and you can relax the restrictions with options

Cross-window communication
win.postMessage(data, targetOrigin) / / to win
//data data targetOrigin specifies the source of the target window
Copy the code

Received, message event

window.addEventListener('message'.function(e) {
    e.data / / data
    e.origin // The sender's source
    e.source// To reference the sender window, reply source.postmessage ()
})
Copy the code

Clickjacking attack

We put a transparent frame with a higher Z-index on a click link, and the user clicks on it, and it falls for us

<style>
iframe { /* Iframe */ from the victim website
  width: 400px;
  height: 100px;
  position: absolute;
  top:0; left: -20px;
  opacity: 0.5; Opacity :0 */
  z-index: 1;
}
</style>

<div>Get rich with a click:</div>

<! -- URL from the victim site -->
<iframe src="/clickjacking/facebook.html"></iframe>

<button>Click here!</button>

<div>... You're cool (I'm actually a handsome hacker)!</div>
Copy the code
Defense:

The traditional defense

if(top ! = =window) {
    top.location = window. If the location}windowIf it's not at the top, place it at the topCopy the code

Window.frames — A collection of “child” Windows (for nested iframes). Window.parent — A reference to the “parent” (external) window. Window.top — a reference to the top-level parent window.

However, it will be bypassed to prevent top-level navigation

window.onbeforeunload = function() {
    return false
}
Copy the code

Ask the user if they want to leave the page, and in many cases they won’t

The sandbox feature prevents changes to top.location

X-frame-options server header X-frame-options allows or disallows pages to be displayed in frames

To display disabled functions, set a style wide 100% height100%

Overwrite the page, block clicks, and remove div if window==top

<style>
  #protector {
    height: 100%;
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 99999999;
  }
</style>

<div id="protector">
  <a href="/" target="_blank">To the site</a>
</div>

<script>
  // If the top-level window is from another source, an error will appear
  // But in this case there is no problem
  if (top.document.domain == document.domain) {
    protector.remove();
  }
</script>
Copy the code

Samesite Cookie Feature Cookies with the Samesite feature are only sent to a website if the website is opened directly

Browser data store

cookie

Cookie is commonly used in login. After login, the server sets a cookie, and the next request will know who is wearing the cookie

console.log(ducument.cookie)/ / display the cookie
document.cooke = ' '// Write, but only add, not replaceCookie format name = value; age=23;
Copy the code

Path path=/admin This cookie is visible under /admin/ admin/some, but not /home

Domain Domain that can access cookies Cookies in the site.com domain cannot be obtained from other.com or subdomain forum.site.com

Expires is in THE GMT format

let date = new Date(Date.now() + 86400e3)
date = date.toUTCstring()
document.cookie = "user=John; expires" + date
Copy the code

If the time is in the past, the cookie is deleted

max-age

document.cookie = "user=John; max-age=3600" // After one hour, the number of seconds from the present time, zero or negative deletion
Copy the code

secure

document.cookie = "user=John; secure" // Can be accessed only in HTTPS mode
Copy the code

Samesite avoid XSRF attack A website with a request related to another website will get another website’s cookie, which can be dangerous samesite=strict from outside the same website, cookies are never sent samesite=lax loose mode, Where the HTTP method is safe and the operation is performed with top-level navigation (not frame), then you can use lax, yuxun cookies

HttpOnly JS cannot fetch cookies or modify them; Because hackers can place JS code such as a web page and wait for the user to visit the page to launch an attack, this option can be prevented. If the website has a bug to the black tech will, hackers may get cookies through JS code will be dangerous

GDRP is the query of many foreign websites, it is a kind of law of them, they must ask the user, in order to track the user’s cookie if we want to set up a cookie with authentication session or tracking ID, then we must get the permission of the user.

LocalStorage, SessionStorage

SetItem (key, value) getItem(key) removeItem(key) Clear () Key (index) // Obtain the key name under the index length // The length of the stored content localStroage is shared in the same-origin page window

traverse

for (let i = 0; i< localStorage.length; i++) {
    let key = localStorage.key(i)
}
Copy the code

SessionStorage only exists on current TAB, refresh and close None

Storage events

The above two update, triggering the event

Key — The key of the changed data (null if the.clear() method is called). OldValue — oldValue (null if new data is added). NewValue — newValue (null if data is deleted). Url – THE URL of the document where the data update occurred. StorageArea – The localStorage or sessionStorage object where the data update occurs.

Network request

Fetch can send requests, similar to Axios.

let promise = fetch(url, [options])


let response = await fetch(url)
if (response.ok) { // Status is 200-- 299, which is true
    let json = await response.json() // Access the Response body as json
} else {
    console.log(response.status) //status is the HTTP status code, for example, 200
}
Copy the code

Response.text () json() formData() blob() arrayBuffer()

Response Header Is a map-like header object in Response. headers

response.headers.get('Content-Type')
Copy the code

The Request header is set in fetch

let response = fetch(url, {
    headers: {
        Authentication: 'secret'}})Copy the code

A POST request

let response = await fecth(url, {
    method: 'POST'.headers: {
        'Content-Type': 'application/json; charset=utf-8'
    },  
    body: JSON.stringfy(obj)
})
Copy the code

FormData

The FormData object represents HTML FormData

let formData  = new FormData([form])
Copy the code
<form id="formElem">
  <input type="text" name="name" value="John">
  <input type="text" name="surname" value="Smith">
  <input type="submit">
</form>

<script>
  formElem.onsubmit = async (e) => {
      e.preventDefault()
      let response = await fetch(url, {
          method: 'POST'.body: new FormData(formElem)
      })
      let res = await response.json()

  }
</script>
Copy the code

Formdata.append (name, value) formdata.append (name, blob, Formdata.delete (name) formdata.get (name) formdata.has (name)

Formdata. set(name, value)

Tracking download progress

The Response. body attribute helps it be ReadableStream — a special object that provides the body chunk by chunk.

// Step 1: Start the fetch and get a reader
let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits?per_page=100');

const reader = response.body.getReader();

// Step 2: Get the total length (length)
const contentLength = +response.headers.get('Content-Length');

// Step 3: Read data
let receivedLength = 0; // The current number of bytes received
let chunks = []; // Array of binary blocks received (including body)
while(true) {
  const {done, value} = await reader.read();

  if (done) {
    break;
  }

  chunks.push(value);
  receivedLength += value.length;

  console.log(`Received ${receivedLength} of ${contentLength}`)}// Step 4: Connect the block to a single Uint8Array
let chunksAll = new Uint8Array(receivedLength); / / (4.1)
let position = 0;
for(let chunk of chunks) {
  chunksAll.set(chunk, position); / / (4.2)
  position += chunk.length;
}

// Step 5: Decode to a string
let result = new TextDecoder("utf-8").decode(chunksAll);

// We are done!
let commits = JSON.parse(result);
alert(commits[0].author.login);
Copy the code

Termination of the fetch

The built-in object AbortController

let controller = new AbortController()
Copy the code

The controller has the method abort(), and the property signal, on which the listener abort() call is set, signal fires the abort event. Signal.aborted is true

So now set the listener on signal and call abort()

let controller = new AbortController()
let signal = controller.signal

signal.addEventListener('abort'.() = > console.log('abort'))

controller.abort()
console.log(signal.aborted)
Copy the code

Fetch works well with AbortController

let controller = new AbortController()
setTimeout(() = > controller.abort(), 1000)
try {
    let response = await fetch(url, {
        signal: controller.signal
    }) 
} catch(err) {
        
}
Copy the code

Terminate, reject, promise

Fetch API

let promise = fetch(url, {
  method: "GET".// POST, PUT, DELETE, etc.
  headers: {
    // The content type header value is usually set automatically
    // Depends on the request body
    "Content-Type": "text/plain; charset=UTF-8"
  },
  body: undefined // String, FormData, Blob, BufferSource, or URLSearchParams
  referrer: "about:client".// or "" to not send the Referer header,
  // Or the current source URL
  referrerPolicy: "no-referrer-when-downgrade".// no-referrer, origin, same-origin...
  mode: "cors"./ / the same - origin, no - cors
  credentials: "same-origin"./ / omit, include
  cache: "default".// no-store, reload, no-cache, force-cache, or only-if-cached
  redirect: "follow"./ / manual, the error
  integrity: "".// a hash like "sha256-abcdef1234567890"
  keepalive: false.// true
  signal: undefined.// AbortController to abort the request
  window: window // null
});
Copy the code

Mode CORS: cross-domain request same-origin: no-cORS: simple cross-domain request

Whether the cookies and HTTP-authorization header same-origin should be sent with the request Accept-control-allow-credentials from cross-source servers are required for JavaScript to be able to access response omit: do not send, even same-origin

CORS

Two types of cross-domain request simple request and other request simple request:

  1. The method is GET POST HEAD
  2. Simple headers allow you to customize only the following headers:

Accept, accept-language, content-language, content-type is application/ x-ww-form-urlencoded, Multipart/form – data or text/plain.

When we try to send a non-simple request, the browser sends a special “preflight” request to the server — asking the server, do you accept such cross-source requests?

Also, non-simple requests are not sent unless the server explicitly acknowledges them with the header.

Cross-domain requests add an Origin header that contains the exact source, the server can check the Origin, and if it agrees to accept such a request, A special header access-Control-allow-origin is added to the response that contains either the allowed source (in our case, javascript. Info), or an asterisk *. Then the response succeeds, otherwise an error is reported.

For cross-source requests, JavaScript can only access the “simple” Response header by default:

Cache-Control Content-Language Content-Type Expires Last-Modified Pragma

To grant JavaScript Access to any other response Headers, the server must send the Access-Control-expose-headers header. It contains a comma-separated list of non-simple header names that should be made accessible. Such as

Access-Control-Expose-Headers: Content-Length,API-Key
Copy the code

For non-simple requests, it sends a “preflight” request for permission before sending such a request. The precheck Request uses the OPTIONS Method, which has no body but two headers: access-Control-request-method Header with methods that are not simple requests. Access-control-request-headers provides a comma-separated list of non-simple HTTP-headers.

If the server agrees to process the request, it will respond with a status code of 200, no body, and header:

Access-control-allow-origin must be * or the source making the request (such as javascript.info) to Allow this request. Access-control-allow-methods must have allowed Methods. Access-control-allow-headers must have a list of allowed Headers. In addition, header access-Control-max-age specifies the number of seconds to cache this permission. Therefore, the browser does not have to send prechecks for subsequent requests that satisfy a given permission.

Precheck, then the server prechecks the response, then the actual request, then the actual response

Js cross-domain requests do not carry any tie (cookies or HTTP authentication), if so, required

fetch(url, {
    credentials: "include"
})
Copy the code

Fetch will send the cookie and our request to the site.

If the server agrees to accept requests with Credentials, in addition to access-Control-allow-Origin, the server should add header Access-Control-allow-credentials: true to the response. Disallow access-Control-allow-Origin to use the asterisk * for requests with credentials. As shown above, it must have an exact source

The URL object

Used to create and parse urls

let url = new URL(url, [base])
url: Full URL, or path onlybase: If the URL has only paths, the URL is generated based on baselet url1 = new URL('https://javascript.info/profile/admin');
let url2 = new URL('/profile/admin'.'https://javascript.info'); equivalentCopy the code
let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);

alert(newUrl); // https://javascript.info/profile/tester

let url = new URL('https://javascript.info/url');
alert(url.protocol); // https:
alert(url.host);     // javascript.info
alert(url.pathname); // /url
Copy the code

SearchParams method append(name, value) — add parameter by name, delete(name) — remove parameter by name, get(name) — get parameter by name, searchParams method append(name, value) — add parameter by name, delete(name) — remove parameter by name, GetAll (name) – Gets all parameters of the same name (this is possible, for example? Set (name, value) — set/replace — sort() — sort parameters by name. … And it is iterable, similar to a Map.

The URL object is automatically encoded

If you use strings, you need to manually encode/decode special characters.

Here are the built-in functions for encoding/decoding urls:

EncodeURI – Encodes the entire URL. DecodeURI – Decoded to the state before encoding. EncodeURIComponent – Encodes URL components, such as search parameters, or hash, or pathName. DecodeURIComponent — decoded to the state before coding.

XMLHttpRequest

Fetch makes it somewhat deprecated

let xhr = new XMLHttpRequest()
xhr.open(method, URL, [async, user, password]) / / initialization
xhr.send([body]) // Send the request

// Listen for responses
xhr.onload = function() {
    // Request complete, HTTp status 400 or 500, and response fully downloaded
}

xhr.oneeror = function() {
    // The request cannot be issued
}

xhr.onprogress = function() {
   // Trigger periodically to report how many downloads
}
Copy the code

XHR attributes: status: HTTP status code, 200, 404 statusText: HTTP status information, 200 is OK, 404 is Not found response: Response Body xhr.timeout = 1000// Timeout

Xhr. responseType sets the response format

xhr.responseType = 'json';
Copy the code

Xhr.readystate to know the current state.

UNSENT = 0; // Initial state
OPENED = 1; // Open is called
HEADERS_RECEIVED = 2; // Response header is received
LOADING = 3; // The response is being loaded (a packet is received)
DONE = 4; // Request completed
Copy the code

Readystatechange event to track them:

xhr.onreadystatechange = function() {
    if (xhr.readyState === 3) {}if (xhr.readyState === 4) {}}Copy the code

Xhr.abort () terminates the request, xhr.status=0

Async false is a synchronous request. Js pauses to wait for completion and continues

The custom header

setRequestHeader(name, value)
xhr.setRequestHeader('Content-Type'.'application/json'GetResponseHeader (name) Gets the header with the given name (Set- cookies andSet-Cookie2 excepted) xhr.getresponseHeader ('Content-Type') getAllResponseHeaders() returns a divisionSet- cookies andSet- All response headers outside Cookie2.Copy the code

About POST xhr.open(‘POST’…) Use the POST method. Xhr.send (formData) sends the form to the server.

let xhr = new XMLHttpRequest()
let json = JSON.stringify({
    name: "John".surname: "Smith"
  });

  xhr.open("POST".'/submit')
  xhr.setRequestHeader('Content-Type'.'application/json')
  xhr.send(json)
Copy the code

Here is another object that has no methods and is dedicated to tracking upload events: xhr.upload.

It generates events, similar to XHR, but xhr.upload fires them only when uploading:

Loadstart — Upload starts. Progress — Fires periodically during upload. Abort — Upload aborts. Error — non-HTTP errors. Load — Upload completed successfully. Timeout — Upload times out (if timeout property is set). Loadend — Upload completes, with or without success.

Cross-domain and fetch policies xhr.withCredentials = true// Can carry cookies

This is me using VUe3 ele. me, if you are interested, I hope you can have a look, thanks github.com/goddessIU/v…

Project preview address goddessiu.github. IO /