This is the 10th day of my participation in the More text Challenge. For more details, see more text Challenge

preface

Five level

  1. I don’t know. I don’t know
  2. I know I don’t know
  3. I know, I know
  4. I don’t know. I know

Brothers above the third level can leave directly.

As for the fifth level, it is not necessary to know or not to know.

Without further further, let’s explore functions that are familiar and unfamiliar to you.

directory

Since the mobile directory is not displayed, write a separate one:

  • setTimeout && setInterval
  • JSON.parse
  • JSON.stringify
  • addEventListener
  • Array.from
  • String.replace
  • window.getComputeStyle
  • localStorage.setItem
  • Console specific

setTimeout && setInterval

grammar

var timeoutID = scope.setTimeout(function[, delay.arg1.arg2. ] );
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);

Copy the code

Var timeoutID = scope. SetTimeout (function[, delay]); For example

setTimeout(() = >{
    console.log(Current time:The ${Date.now()}`);
}, 1000)
Copy the code

Let’s take a look at the third setTimeout(code[, delay]). Code is a code string, and the underlying implementation is to call eval. You might wonder how you know, because MDN has an explanation for the code parameter.

code

An alternative syntax that allows you to include a string instead of a function, which is compiled and executed when the timer expires. This syntax is not recommended for the same reasons that make using eval() a security risk.

So that code is equal to this code

setTimeout( 'console.log(" Current time:The ${Date.now()}") `.1000)
Copy the code

Some of these digs may be posted directly to the browser’s console for testing, but I have to warn you that you probably won’t be able to do it correctly and will receive a prompt like the one below

[Report Only] Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an   
allowed source of script in the following Content Security Policy directive: "script-src .........Copy the code

This is because CSP intercepts. For more information on CSP, see Content-Security-Polic or The Introduction to Content Security Policy tutorial

SetTimeout (function[, delay, arg1, arg2… ), starting with the third argument, will be passed to the callback function. Let’s look at some code

setTimeout((startTime, tip) = >{
    const endTime = Date.now();
    console.log("Time has passed.", endTime - startTime, "ms," ,tip);  // Time has passed 501 ms, it is time to rest
},500.Date.now(), "It's time to rest.");
Copy the code

Actually clearTimeout, clearInterval also have a little something, clearTimeout can remove setInterval? What about the other way around?

var ticket = setTimeout(() = >{
    console.log("Execute after 100ms");
},100);

var ticket2 = setTimeout(() = >{
    console.log("Execute after 200ms");
},200);
clearInterval(ticket);

// Execute after 200ms
Copy the code

Some people will say, this this this…… Young man don’t take it so seriously.

An aside:

There is a legend setTimeout 4ms minimum interval. If setTimeout is nested more than four times, the 4ms constraint will apply only after the fifth time. For more information, see the HTML Standard timer-and-user-prompts. You can also go to MDN setTimeout and test it yourself.

Here I should add, standards to standards, implementation to implementation, browser manufacturers so many, ha.

JSON.parse

grammar

JSON.parse(text)
JSON.parse(text, reviver)
Copy the code

We use the first one 99.99% of the time.

The reviver arguments are expressed in TypeScript and look something like this (key:string, value: any)=> any.

If the reuse program only converts some values and not others, be sure to return all unconverted values as is, or they will be removed from the result object.

So for example, once you convert it to an object, the IDCard property is gone.


JSON.parse(JSON.stringify({
  name: "tom".age: 18.phone: "15888787788".IDCard: "xxxx"
}), (key, value) = >{
  
  if(key === "IDCard") {return undefined
  }
  return value;
    
});   // {name: "tom", age: 18, phone: "15888787788"}
Copy the code

Here are two additions:

  1. When converted by json. parse, it is depth-first traversal
  2. The value of the last key is null

Look at the code:


JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}'.(key, value) = > {
  console.log(key); // log the current property name, the last is "".
  return value;     // return the unchanged property value.
});

/ / 1
/ / 2
/ / 4
/ / 6
/ / 5
/ / 3
/ / ""
Copy the code

JSON.stringify

grammar

JSON.stringify(value)
JSON.stringify(value, replacer)
JSON.stringify(value, replacer, space)
Copy the code

I won’t say much about the first one.

The last two parameters are described as follows

Replacer optional

  • If the parameter is a function, each property of the serialized value is converted and processed by the function during serialization;
  • If the parameter is an array, only the property names contained in the array will be serialized into the final JSON string;
  • If this parameter is null or not provided, all the properties of the object are serialized.

Space optional

Specifies a blank string to use for indentation, used to beautify output (pretty-print);

  • If the argument is a number, it indicates how many Spaces there are; The upper limit is 10. If the value is less than 1, there is no space.
  • If the argument is a string (when the string is longer than 10 characters, take the first 10 characters), the string will be treated as Spaces;
  • If this parameter is not provided (or null), there will be no Spaces.

At this point, some of you were surprised. There’s been a lot written about it in the Nuggets

  • Explode the power of json.stringify () without you knowing it
  • Interesting JSON. Parse, json. stringify
  • The deep copy series ———— implements a json.stringify and json.parse itself

Of course I said two things:

  • toJSON
  • Space parameters

ToJSON: When an object to be converted has a toJSON method defined, the toJSON value is returned directly. Here’s an example:

var obj = {
  foo: 'foo'.toJSON: function () {
    return 'bar'; }};JSON.stringify(obj);      // '"bar"'
Copy the code

The space: parameter is used to beautify the converted format, especially useful when saving JSON files, for example. Of course, the following code you put into the browser, some browsers may not see the effect, in nodejs execution, then save the file to see the effect.

JSON.stringify({ uno: 1.dos : 2 }, null.'\t')
/ / '{\
// "uno": 1, \
// "dos": 2 \
/ /} '
Copy the code

addEventListener

Right here, right here, and you doubt I know how to use it. I really think, if you look at more than 50 percent of the people here, it’s not good. Wait to see, if it is true not plenary, trouble comments area comments together to watch the author. ;

target.addEventListener(type, listener, options);
target.addEventListener(type, listener, useCapture)
Copy the code

The reliability of the four nines, 99.9999% of the notification, is fully aware of the case where the third parameter is a Boolean. I won’t talk about it.

The options of the optional

Available options:

  • Capture: Boolean, indicating that the listener will be triggered when the event capture phase of this type is propagated to the EventTarget.
  • Once: Boolean: indicates that the listener is invoked at most once after being added. If true, the listener is automatically removed after it is called.
  • Passive: Boolean. If the value is true, the listener will never call preventDefault(). If the listener still calls the function, the client will ignore it and throw a console warning. View the scrolling performance improved with passive mode for more information.
  • Signal: AbortSignal. When the abort() method of AbortSignal is called, the listener is removed.

once

This is the pattern we are familiar with, such as once, EventEmitter, socket. IO, etc.

In fact, Window itself is somewhat of a subscription publishing center:

function _dispatch(type, data) {
    const ev = new CustomEvent(type, { detail: data });
    window.dispatchEvent(ev);
}

window._on = window.addEventListener
window._emit = _dispatch;
window._once = (type, callback) = > {
    window.addEventListener(type, callback, {
        once: true.capture: true})}window._on("event-x".(ev) = > {
    console.log(Event-x received data:, ev.detail);
});

window._once("event-once".(ev) = > {
    console.log(Event-once received data:, ev.detail);
}, {
    once: true});window._emit("event-x", {
    uid: 100.message: "i love you"
})

window._emit("event-once", {
    uid: -100.message: "you love me"
});

window._emit("event-once", {
    uid: -100.message: "you love me"
});

{uid: 100, message: "I love you"}
{uid: -100, message: "you love me"}
Copy the code

In fact, this capability applies to any object that inherits from EventTarget, not just Windows.

passive

View the scrolling performance improved with passive mode for more information

signal

This signal is part of the AbortController, which is used to terminate requests.

And what it does here is it removes the listener.

Code like this, if commented controller.abort(); “, you get two messages.

var controller = new AbortController();
var signal = controller.signal;

function _dispatch(type, data) {
    const ev = new CustomEvent(type, { detail: data });
    window.dispatchEvent(ev);
}

window.addEventListener("event-x".ev= > {
    console.log("Event-x: Data received:", ev.detail);
}, {
    signal
});

_dispatch("event-x"."i love you");
/ / termination
controller.abort();
_dispatch("event-x"."i love you");

// event-x: received data: I love you
Copy the code

To this if you really plenary, trouble comments area comments together to watch the author.

Array.from

Array.from(arrayLike[, mapFn[, thisArg]])
Copy the code

The point is this mapFn:

ApFn Optional If this parameter is specified, the callback function is executed for each element in the new array.

So easy! Let’s make an array from 1 to 100.

    Array.from({length:100}, (val, index)=>  index + 1 );
Copy the code

string

Array.from('foo'); 
// [ "f", "o", "o" ]
Copy the code

Set

const set = new Set(['foo'.'bar'.'baz'.'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]
Copy the code

Map: Map: Array: array: array: array: array

const map = new Map([[1.2], [2.4], [4.8]]);
Array.from(map); // equivalent to [...map.entries()]
// [[1, 2], [2, 4], [4, 8]]

const mapper = new Map([['1'.'a'], ['2'.'b']]);
Array.from(mapper.values());
// ['a', 'b'];

Array.from(mapper.keys());
/ / (' 1 ', '2');
Copy the code

Sequence generator

const range = (start, stop, step) = > Array.from(
    { length: (stop - start) / step + 1}, 
    (_, i) = > start + (i * step)
);

// Generate numbers range 0.. 4
range(0.4.1);
// [0, 1, 2, 3, 4]
Copy the code

Range comes with Python, and you can see how simple our JS implementation is.

String.replace

str.replace(regexp|substr, newSubStr|function)

Special variable name

The special variable name makes the replace belong to the afterlife, and the following $2 and $1 are string arguments.

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
// Smith, John
console.log(newstr)
Copy the code

All string arguments are as follows:

The variable name On behalf of the value of the
$$ Insert a “$”
$& Inserts the matching substring.
$` Inserts the content to the left of the currently matched substring.
$’ Inserts the content to the right of the currently matched substring.
$n If the first argument is a RegExp object and n is a non-negative integer less than 100, insert the NTH parenthesy-matched string. Tip: The index starts at 1. If the NTH grouping does not exist, then the matched to content is replaced with literals. For example, if there is no third group, “$3” will be used to replace the matched content.
$ Where Name is a group Name. If there is no grouping (or no match) in the regular expression, the variable is treated as an empty string. Only in browsers that support named group capture

The second argument is the function

To make it easier to understand, let’s look at:

function replacer(match, p1, p2, p3, offset, string) {
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(The '-');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString);  // abc - 12345 - #$*%
Copy the code

P1, p2, p3 correspond to special variable names $1, $2, $3,

For more details, refer to the MDN function parameters

window.getComputeStyle

As you all know, CSS has weights, there are styles, there are all kinds of things in CSS, there are browser default styles, and so on. God knows which ones will be in effect. Ghost is equal to this getComputeStyle.

Here’s an example:

<style>
 #elem-container{
   position: absolute;
   left:     100px;
   top:      200px;
   height:   100px;
   z-index: 1;
 }
</style>

<div id="elem-container">dummy</div>

<script> 
    let elem = document.getElementById("elem-container");
    const ps =  window.getComputedStyle(elem,null)
    console.log(ps.. getPropertyValue("height")); // 100px
</script>
Copy the code

Read the value way

  1. ps.getPropertyValue(“z-index”);
  2. ps[“z-index”];
  3. Ps.zindex (read with style)

All three of the above are feasible.

The return value is the parsed value

The return value of getComputedStyle is the resolved value, often the same as the computed value in CSS2.1. But for some of the older properties, like width, height, padding, the values are the application values again.

Calculated value: For example, if an element’s attribute values are font-size:16px and padding-top:2em, the padding-top is calculated at 32px (twice the font size). Application values: for example, span specifies position: Absolute. Display becomes block.

Secondly, the value is not necessarily in the same format as the set value. For example, if you set color to red, the returned value is RGB (255, 0, 0). For example, if you say transform transform: translate(10px, 10px), the return value is matrix(1, 0, 0, 1, 10, 10).

The second parameter is pseudoElt

PseudoElt optionally specifies a string of pseudoelements to match. Ordinary elements must be omitted (or null)

Is used to get the final style of pseudo-elements, the common ones are ::after, ::before, ::marker, ::line-marker.

<style>
    h3::after {
        content: "rocks!";
    }
</style>

<h3>generated content</h3>

<script>
    let h3 = document.querySelector('h3'),
    result = getComputedStyle(h3, '::after').content;
    alert(`the generated content is: ${result}`);
    console.log(`the generated content is: ${result}`);
    // the generated content is: "rocks!"
</script>
Copy the code

At the end, getComputeStyle will trigger a rearrangement, and of course a lot of things that get width and height will trigger a rearrangement. Just keep that in mind.

localStorage && sessionStorage

Storage events

This is localstorage.setitem, which is not much to say in itself. There is a corresponding storage event that listens for changes in the value of the storage.

A.html

localStorage.setItem("data", JSON.stringify({
    a: 1,
    b: 3
}))
Copy the code

B.html

window.addEventListener("storage", (ev) => {
    console.log("key:", ev.key);   // key: data
    console.log("oldValue:", ev.oldValue); // oldValue: null
    console.log("newValue:", ev.newValue);  // newValue: {"a":1,"b":3}
    console.log("storageArea:", ev.storageArea); 
    // storageArea: Storage {ev: "{\"a\":1,\"b\":3}", length: 1}
    console.log("url:", ev.url); // url: http://127.0.0.1:8080/A.html
});
Copy the code

Hide two details from above

  1. A.html calls setItem and B.TML listens for events

This is because A.HTML itself cannot listen to this event

  1. Storage event objects have oldValue and newValue properties

As you can see, setting the same value does not trigger an event.

Let setItem’s page listen for storage events

Principle, override the setItem event

var originalSetItem = sessionStorage.setItem;
localStorage.setItem = function (key, newValue) {
    var itemEvent = new CustomEvent("c-storage", {
        detail: {
            oldValue: localStorage.getItem(key),
            newValue,
            key,
            url: location.href
        }
    });
    window.dispatchEvent(itemEvent);
    originalSetItem.apply(this.arguments);
}

window.addEventListener("c-storage".function (ev) {
    console.log("ev", ev.detail);
}
// key: "data"
// newValue: 1624506604683
// oldValue: "1624506595323"
/ / url: "http://127.0.0.1:8080/LA.html"

localStorage.setItem("data".Date.now());
Copy the code

Internet Explorer seems to have a bug, with the page Storage change monitor has been mentioned

Console specific

The console series

Console. table, console.time, console.assert0, console.count, console.group I won’t say.

Log console.log defines the style: the source is colorful console.log

Const styles = ['color: green', 'background: yellow', 'font-size: 30px', 'border: 1px solid red', 'text-shadow: 2px 2px black', 'padding: 10px', ].join('; '); // 2. Join the items with semicolons to form a string // 3. Pass the styles variable console.log('%cHello There', styles);Copy the code

Output:

Series of symbolic functions

methods instructions
The $_ One last estimate
$(selector) document.querySelector
? (selector) document.querySelectorAll
$x(path) XPathEvaluator
$x("/html/body")
Copy the code

other

GetEventListeners: Have you ever run into a request to query all the listener functions for an element, but there is no such thing on the page? But the console does have a picture

Clear: clear the console

Write in the last

Writing is not easy, but praise and comment are my biggest motivation.

A page Storage change listener setTimeout setInterval Map relationship with an array of timer-and-user-prompts Colorful console. Log Recommend several good console debugging tips