"
midnight,
pushed the door to the courtyard,
courtyard is ripe, 161187f61c01db has a red fruit quietly falling,
I cut a moonlight wrapped my heart.
July’s insect sound is the three hundred Tang poems that have blown up the thread.
all broken
tin rhyme: lonely lonely lonely lonely.
I said: Fisherman, you are not as good as a bug. You haven't returned for three years.
desert blind alley,
only words,
you wish the moon and stars when the messenger care,
if I have to cut a length of salty white cloth,
stains wound pain,
I would know,
you have not come back.
Friends who follow this series, it’s been a long time because of some things. I’m really sorry. At the beginning of August, this series is back. In fact, I have been thinking, what is the meaning of "108 styles of front-end installation skills"? Is it to bring some development skills? Is it to integrate some details that everyone has overlooked? Is it really used to pretend? Is it more technical or fun? This is a question of trade-offs. Partial techniques will lose some interest; partial interest will lose some depth. In my opinion, there are actually a lot of purely technical articles. I hope to bring more fun to the life of programmers. In the remaining articles of the series, I will still strive to provide more life for programmers from all angles. Add some special colors.
A summary of the series of articles:
- Front-end installation skills 108 formula (1)
- front-end installation skills 108 formula (two)
- Front-end installation skills 108 formula (3)
- Front-end loading skills 108 formula (4)
- browser work: Chrome V8 makes you
The style of the article is limited, and the quotation part will be marked at the end of the corresponding section.
Type 55: Have you ever seen the page dance? —— That high moving page is like my lost youth in those years
Do you still remember the magical Apple and Douyin? As a front-end, have you ever thought about make the page high and dance ?
Look at the effect first:
The following code can be executed directly in the console and is slightly longer. You can skip directly to the end of this section and use the short JS introduction method to experience ( with music effects )
setTimeout(letDance, 1000);
var bgmSrc =
'https://nd002723.github.io/carnival/audio/Martin%20Jensen%20-%20Fox%20(Loop%20Remix).mp3';
var cssHref = 'https://nd002723.github.io/carnival/css/high.css';
function letDance() {
function loadCss() {
//将css文件引入页面
var myCss = document.createElement('link');
myCss.setAttribute('type', 'text/css');
myCss.setAttribute('rel', 'stylesheet');
myCss.setAttribute('href', cssHref); //css文件地址
myCss.setAttribute('class', l);
document.body.appendChild(myCss);
}
function h() {
var e = document.getElementsByClassName(l);
for (var t = 0; t < e.length; t++) {
document.body.removeChild(e[t]);
}
}
function p() {
var e = document.createElement('div');
e.setAttribute('class', a);
document.body.appendChild(e);
setTimeout(function () {
document.body.removeChild(e);
}, 100);
}
function getSize(e) {
//获取目标的宽高
return {
height: e.offsetHeight,
width: e.offsetWidth,
};
}
function checkSize(i) {
//判断目标大小是否符合要求
var s = getSize(i); //获取目标的宽高
return (
s.height > minHeight &&
s.height < maxHeight &&
s.width > minWidth &&
s.width < maxWidth
); //判断目标是否符合条件
}
function m(e) {
var t = e;
var n = 0;
while (!!t) {
n += t.offsetTop;
t = t.offsetParent;
}
return n;
}
function g() {
var e = document.documentElement;
if (!!window.innerWidth) {
return window.innerHeight;
} else if (e && !isNaN(e.clientHeight)) {
return e.clientHeight;
}
return 0;
}
function y() {
if (window.pageYOffset) {
return window.pageYOffset;
}
return Math.max(
document.documentElement.scrollTop,
document.body.scrollTop
);
}
function E(e) {
var t = m(e);
return t >= w && t <= b + w;
}
function setBgm() {
//设置音乐
var e = document.createElement('audio');
e.setAttribute('class', l);
e.src = bgmSrc; //bgm地址
e.loop = false;
e.addEventListener(
'canplay',
function () {
setTimeout(function () {
x(k);
}, 500);
setTimeout(function () {
N();
p();
for (var e = 0; e < O.length; e++) {
T(O[e]);
}
}, 15500);
},
true
);
e.addEventListener(
'ended',
function () {
N();
h();
},
true
);
e.innerHTML =
' <p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p> <p>';
document.body.appendChild(e);
e.play();
}
function x(e) {
e.className += ' ' + s + ' ' + o;
}
function T(e) {
e.className += ' ' + s + ' ' + u[Math.floor(Math.random() * u.length)];
}
function N() {
var e = document.getElementsByClassName(s);
var t = new RegExp('\\b' + s + '\\b');
for (var n = 0; n < e.length; ) {
e[n].className = e[n].className.replace(t, '');
}
}
var minHeight = 3; //最小高度
var minWidth = 3; //最小宽度
var maxHeight = 800; //最大高度
var maxWidth = 1400; //最大宽度
var s = 'mw-harlem_shake_me';
var o = 'im_first';
var u = ['im_drunk', 'im_baked', 'im_trippin', 'im_blown'];
var a = 'mw-strobe_light';
var l = 'mw_added_css'; //最终要移除的css
var b = g();
var w = y();
var C = document.getElementsByTagName('*');
var k = null;
for (var L = 0; L < C.length; L++) {
var targetDiv = C[L];
if (checkSize(targetDiv)) {
if (E(targetDiv)) {
k = targetDiv;
break;
}
}
}
if (targetDiv === null) {
//如果没找到合适大小的
console.warn('没能找到合适的大小. 换一个页面试试?.');
return;
}
loadCss(); //将自定义css文件引入页面
setBgm(); //添加背景音乐
var O = [];
for (var L = 0; L < C.length; L++) {
var targetDiv = C[L];
if (checkSize(targetDiv)) {
O.push(targetDiv);
}
}
//网页整体倾斜效果(这块儿本来是JQuery实现的,为了避免引入JQuery,做了改动。)
var style = document.createElement('style');
style.type = 'text/css';
try {
style.appendChild(
document.createTextNode(
'body{overflow-x:hidden;transform: rotate(1deg);-webkit-transform: rotate(1deg);-moz-transform: rotate(1deg);-o-transform: rotate(1deg);-ms-transform: rotate(1deg)}'
)
);
} catch (ex) {
style.styleSheet.cssText = 'body{background-color:red}'; //针对IE
}
var head = document.getElementsByTagName('head')[0];
head.appendChild(style);
}
Or more concisely, type the following code in the page URL bar or console to experience directly:
In the browser address bar paste the following words, there is three things to note , one must be an existing page content; and second, if it is by copy paste the code into the browser address bar, then, IE and Chrome willjavascript:
at the beginning of the code is automatically removed, so it needs to be manually added for correct execution. Although Firefox will not be automatically removed, it does not support running JS code in the address bar at all; third, the referencedcarnival.js
will rely onJQuery
(if not It’s okay, but the page is missing a slanting effect).
javascript: void (function () {
var d = document,
a = 'setAttribute',
s = d.createElement('script');
s[a]('tyle', 'text/javascript');
s[a]('src', 'https://nd002723.github.io/carnival/js/carnival.js');
d.head.appendChild(s);
})();
Type 56: In the past, the golden-level Baiyutang, now only sees the green pine-can the browser incognito mode really be invisible?
Incognito mode and unique device identification
We all know that the browser incognito mode can prevent others from knowing what websites you have visited and what operations you have done. In incognito mode, the opened web pages and downloaded files will not be recorded in your browsing history and download history. middle. After you close all open incognito windows, the system will delete all new cookies. But, is the stealth mode really invisible? Do you really fail to recognize that you have visited the same website multiple times in incognito mode? If this is the case, it is definitely a tool for UV (unique visitor). I tried the personal blog , and it is really like this (I used without garlic ). Then whoever has more UV than me Ah, 😄😄😄, but wait, there seems to be something wrong... Anthracene, I am a programmer 🤔, what if products and data analysts need accurate data? Does the page that does not need to log in (such as community articles) need to eliminate the incognito mode brushing UV traffic? Does the voting site that does not need to log in need to eliminate the incognito mode and repeatedly vote like it? Well, this has to introduce the concept of device unique identification
In the development scenario, uniquely identifying a device is a basic function that can have many application scenarios, such as software authorization (how to ensure that your software can be used on a specific machine after authorization), software license, device identification, and device identity Identify etc.
If you want to obtain the unique identification of the device, you may think of ideas like IMEI, Android ID, MAC address, etc., but the official document Android 10 has the following two expressions:
- Starting from Android 10, apps must have the
READ_PRIVILEGED_PHONE_STATE
to access the device's non-resettable identifier (including IMEI and serial number). - By default, on devices with Android 10 or higher, the system will transmit a randomly assigned MAC address.
A computer may have multiple network cards and multiple MAC addresses. Another more fatal weakness of the MAC address is that the MAC address is easy to manually change.
As for the Android ID, it does not have true uniqueness. ROOT, flashing, restoring factory settings, applications with different signatures, etc. will cause the acquired Android ID to change, and the bugs of the systems customized by different manufacturers will cause different devices to produce The same Android ID.
Some other methods to obtain the unique identification of the device, this article has a more comprehensive discussion:
Obtain the unique identifier of the device (Unique Identifier): Windows system
And if we go back to our front-end scenario, the above methods have many limitations. For example, some require franchise permissions, and some need to rely on the cooperation of native development. Then, is there a only requires the front-end to participate in What about a unique identification scheme that can get a good accuracy rate? —— It's time for the browser fingerprint to come out.
FingerPrint is what we often call fingerprint recognition, which uses the texture pressed down on the front of the finger and thumb to authenticate identity. Fingerprints are a reliable method of identifying identity and are unique, because the texture arrangement on each finger of each person is different and does not change due to development or age. The browser fingerprint refers to a string composed of various information of the browser, such as CPU core number, graphics card information, system font, screen resolution, browser plug-in, etc., and can almost absolutely locate a user. Even if you use the privacy window mode of the browser, cannot be avoided.
This is a passive way of identification. In other words, in theory, if you visit a certain website, then this website can recognize you. Although you don’t know who you are, you have a unique fingerprint. In the future, whether it is advertising, precise push, and security protection , Or other things about privacy, are very convenient.
There are also some methods for the recognition of incognito mode in the market, such as checking FileSystem API
of Chrome, and judging by the difference between incognito mode and non-incognito mode, script execution and writing speed to the browser file system, etc.
BrowserLeaks
For a long time, people have believed that IP addresses and cookies are the only reliable digital fingerprints used to track people online. But after a while, when modern network technology allows interested organizations to use new methods to identify and track users without their knowledge and unavoidable circumstances, things get out of control.
BrowserLeaks is about browsing privacy and web browser fingerprinting. Here, you will find a library of web technology security testing tools that will show you what types of personally identifiable data may be leaked and how to protect yourself from such leaks. This website provides multiple types of fingerprints, including IP address, geographic location, Canvas, WebGL, WebRTC, fonts, etc.
If you are very interested in the technical principles, you can enter BrowserLeaks , click the corresponding card title to view and understand, such as HTML5 Canvas Fingerprinting page, it will give your Canvas fingerprint and its uniqueness rate and other information; also You can use the explore browser fingerprints .
Implement Canvas Fingerprinting
Canvas Fingerprinting (Canvas fingerprint) draws a picture of a specific content based on Canvas, and uses the canvas.toDataURL() method to return the base64 encoded string of the picture content. For the PNG file format, it is divided into chunks, and the last piece is a 32-bit CRC check. Extracting this CRC check code can be used for the unique identification of the user. Canvas uses HTML5 canvas API and JavaScript to dynamically generate the images you want. Like other tracking technologies, this method has been adopted by thousands of websites, including the well-known area of advertising.
The following is a simple implementation of Canvas fingerprint, the principle is actually relatively simple, you can refer to the notes if you don't understand:
// PHP 中,bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。字符串可通过使用 pack() 函数再转换回去
// 下面是PHP 的 bin2hex 的 JavaScript 实现
function bin2hex(s) {
let n,
o = '';
s += '';
for (let i = 0, l = s.length; i < l; i++) {
n = s.charCodeAt(i).toString(16);
o += n.length < 2 ? '0' + n : n;
}
return o;
}
// 获取指纹UUID
function getUUID(domain) {
// 创建 <canvas> 元素
let canvas = document.createElement('canvas');
// getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性
let ctx = canvas.getContext('2d');
// 设置在绘制文本时使用的当前文本基线
ctx.textBaseline = 'top';
// 设置文本内容的当前字体属性
ctx.font = "14px 'Arial'";
// 设置用于填充绘画的颜色、渐变或模式
ctx.fillStyle = '#f60';
// 绘制"被填充"的矩形
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = '#069';
// 在画布上绘制"被填充的"文本
ctx.fillText(domain, 2, 15);
ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
ctx.fillText(domain, 4, 17);
// toDataURL返回一个包含图片展示的 data URI
let b64 = canvas.toDataURL().replace('data:image/png;base64,', '');
// atob() 方法用于解码使用 base-64 编码的字符串;base-64 编码使用方法是 btoa() ,第十九式中有介绍
let crc = bin2hex(atob(b64).slice(-16, -12));
return crc;
}
// 调用时,你可以传入任何你想传的字符串,并不局限于传递domain,这里只是为了便于区分
console.log(getUUID('https://www.baidu.com/'));
PHP bin2hex() function
The test results show that the CRC check code generated when the same browser accesses the domain is always unchanged. It can be simply understood that the , on different operating systems and different browsers, the generated image content is actually not exactly the same . There may be several reasons for this situation:
- In terms of image format, different web browsers use different graphics processing engines, different image export options, and different default compression levels.
- At the pixel level, the operating systems each use different settings and algorithms for anti-aliasing and sub-pixel rendering operations.
- Even with the same drawing operation, the final image data is still different at the hash level.
FingerprintJS
FingerprintJS is a fast browser fingerprint library, purely JavaScript
without any dependencies. By default, the Murmur Hash
algorithm is used to return a 32-bit integer, and the Hash function can be easily replaced. At the same time, he is also very lightweight: gzipped
, only 843 bytes
, and the accuracy of anonymously identifying web browsers is as high as 94%
.
MurmurHash is a non-encrypted hash function, suitable for general hash retrieval operations. It was invented by Austin Appleby in 2008, and there have been many variants, all of which have been published in the public domain. Compared with other popular hash functions, MurmurHash's random distribution characteristics perform better for keys with strong regularity.
The use of FingerprintJS is also relatively simple:
import FingerprintJS from '@fingerprintjs/fingerprintjs';
// 应用启动时初始化:Initialize an agent at application startup.
const fpPromise = FingerprintJS.load();
(async () => {
// Get the visitor identifier when you need it.
const fp = await fpPromise;
const result = await fp.get();
// This is the visitor identifier:
const visitorId = result.visitorId;
console.log(visitorId);
})();
The above methods can obtain more than 90% of unique browser fingerprints, which may not be completely unique. For example, rewriting related canvas methods and using owl browser will still invalidate related methods. However, technical means are more often just a solution in a general sense, increasing the barriers and costs of cracking. I think it is sufficient to support development in common scenarios.
Owl browser is a browser based on chromium code modification and compilation. Various APIs have been modified from the bottom, which can be handed to users to customize and return various data, such as Canvas, Webgl, AudioContext, WebRTC, fonts, UserAgent, and screen resolution. , CPU core number, memory size, plug-in information, language and other information, so that you can completely avoid being "generated" unique user fingerprints. Because online companies, advertisers and developers like to track your online activities and actions in order to provide you with targeted advertising, usually, people think that this is an infringement of user privacy.
With a unique browser fingerprint, we can bring relevant fingerprints when similar to UV statistics, likes, and votes. Naturally, it is possible to determine to a great extent whether users have swiped tickets or swiped traffic, but , browser fingerprint technology is after all a double-edged sword . While solving the above problems, it will inevitably bring more information leakage troubles to users.
Type 57: JavaScript Puzzlers!-a question bank that can be used to pretend
As a programmer, requirements are everywhere, bugs are everywhere, and naturally, pretense can also be everywhere. Think back to every interview you had, have you ever been despised or show off by the interviewer? Think back to every communication between you and your colleague, whether you have ever been speechless and uncomfortable with the weird interview questions displayed by your colleague or the strange tricks 😓, but you want to show back but suffer from a moment of "shyness in your head", JavaScript Puzzlers! is one of them. With all kinds of websites expressing JavaScript problems, now my mother is no longer afraid that I can't find any code/problems that can be forced.
We might as well look at a few topics first:
var min = Math.min(),
max = Math.max();
min < max; // 答案: false
// 有趣的是, Math.min 不传参数返回 Infinity, Math.max 不传参数返回 -Infinity 😆
// 这个还是相对容易的
var name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
// 答案:Goodbye Jack
'1 2 3'.replace(/\d/g, parseInt); // 答案: 1, NaN, 3
No, I'm a front-end engineer. Can I call it pretending to be an engineer? that is not very useful, but this is called the great wisdom , 161187f61c0eae, haha~
Having said that, these perverted topics involve a wide range of knowledge points. If you can grasp the principles behind these topics, you may have a significant improvement in your understanding of JavaScript. The topics are listed below for your reference:
At present, due to unknown reasons, maybe there are too many forced answer questions 😄, JavaScript Puzzlers! The website is no longer accessible. Fortunately, you can check the specific questions and analysis through the following two GitHub links.
- 44 Javascript Abnormal Questions (
- 44 Javascript abnormal questions (Part 2)
- JavaScript Puzzlers!
- jsisweird
Type fifty-eight: awesome browser address bar
As a front-end developer, we even spend more time with the browser every day than our girlfriend/boyfriend (if any 😄) stay with you. Think about every morning that is "not so expectant" , Every twilight that races against the clock to complete the task, only the browser and editor have been your loyal partners, then, do you know the browser? Do you know the address bar where you http://localhost:3000/
This section takes you to know those interesting details about the address bar.
Run JavaScript code in browser address bar
Yes, you read that right. In the "Browser address bar to run JavaScript code", the practice is to javascript:
followed by the statement to be executed. It should be noted that if copies and pastes the code to the browser address bar, IE and Chrome will automatically remove javascript:
at the beginning of the code, so it needs to be manually added to execute correctly. In addition, you need to run javascript:
in the address bar of the website, but not on the newly opened empty tab page, otherwise it will not take effect.
// 点击确定后,会接着弹出:孤舟蓑笠翁,独钓寒江雪,点击取消则不会弹出
javascript: if (confirm('千山鸟飞绝,万径人踪灭'))
alert('孤舟蓑笠翁,独钓寒江雪');
Run HTML code in browser address bar
If there are many people who know "Run JavaScript code in browser address bar", there are fewer people who know "Run HTML code in browser address bar". You can directly access the address bar of non-IE kernel browsers. Run the HTML code! Enter the following code in the address bar and press Enter to run, the page shown in the figure below will appear:
data:text/html,
<h1>Nothing is given, Everything is earned!</h1>
The browser can be your notepad
This is still a fuss on the browser address bar. Copy and paste the following code into the browser address bar. After running, the browser becomes a simple original editor. Not much to say, just try it.
data:text/html,
<html contenteditable></html>
In addition, add a universal browser cancel and close the page shortcut keys: under MAC OS, command + shift + t
; Windows: ctrl + shift + t
. The to reopen the closed page , you can press it all the time, and the closed pages will be restored in turn~, or else, see what your friends have done and see if they will be beaten 😜
References: These little-known front-end cold knowledge, have you GET it?
Type 59: Wang Feng shed tears when he saw it-how did I easily get on Baidu's hot search?
"Wang Feng is on the headlines" has always been a stalk in the entertainment industry. Every time I see Wang Feng on the Weibo hot search list, I think I can reach the top of the list. I don't want to be suppressed by other hot spots. No matter how hard the fans work, Wang Feng still Too late to make headlines!
Anthrace, if Wang Feng is a front-end engineer, wouldn't the hot search work be done in minutes? Even if you don’t understand HTML, you just need to know the contenteditable
attribute of HTML5, and enter a document.body.contentEditable='true';
console. The hot search is not just changing it, you want as many as you want😄.
Anthracene 🤔, after learning this trick, you can even confess to the target easily through hot search... But as professional web application and website developer , how can we be satisfied with this?
In the same way, we also use the contenteditable
attribute in HTML5 to cleverly add an editable style tag to the body. Then we can modify this style on the page. Think about it... there is not much use, ha Haha 😂, but having said that, this attribute is still very useful on some rich text editors. Many rich text editors are based on contenteditable
. For details, please refer to explain the contenteditable rich text editor .
<style style="display:block; height:50px;" contenteditable>
body {
background: red;
}
</style>
Effect picture (picture from the reference article below):
Do you think contenteditable
only has true
and false
? In fact, its optional values include:
- contenteditable=""
- contenteditable="events"
- contenteditable="caret"
- contenteditable="plaintext-only"
- contenteditable="true"
- contenteditable="false"
In addition to the contenteditable
attribute of HTML5, there is actually user-modify
can achieve similar effects. user-modify
can take the following four values:
read-only
read-write
write-only
read-write-plaintext-only
Among them, write-only
don't care. In this era, there is basically no browser support, and it is estimated that there will not be any in the future. read-only
means read-only, which is the default state of common elements. Then, read-write
and read-write-plaintext-only
will make the element behave like a text field, you can focus and input content, the former can enter rich text, and the latter can only enter plain text.
You can view the specific effects by reviewing the elements and adding CSS styles to the elements, or you can directly see Zhang Xinxu’s CSS user-modify property behavior test example page demo.
- These little-known front-end cold knowledge, have you all GET?
- small tip: How to make contenteditable elements only input plain text
Sixtieth formula: I look back suddenly, but the person is there, in the dimly lit place-where did my mouse go?
This technique of hiding the mouse on the page is actually not worth mentioning, and it is useless. You can copy the following code directly to the console to try (if you hang up the right-click menu on the page at this time, you can still see the mouse):
var style = document.createElement('style');
document.head.appendChild(style);
style.type = 'text/css';
style.styleSheet
? (style.styleSheet.cssText = '* { cursor: none;!important; }')
: style.appendChild(
document.createTextNode('* { cursor: none;!important; }')
);
The principle is very simple, just set the cursor
attribute to none
:
* {
cursor: none !important;
}
Or enter the following in the browser address bar:
IE and Chrome will automatically hide the previousjavascript:
and use the latter part as a query field. You need to copy the following code and paste it and manually addjavascript:
front, and then the effect of pressing enter will come out.
javascript:function play(){var style = document.createElement('style');document.head.appendChild(style);style.type = 'text/css';style.styleSheet ? (style.styleSheet.cssText = '* { cursor: none !important; }') : style.appendChild(document.createTextNode('* { cursor: none !important; }'));}play();
References: Front end play casually
Sixty-first style: come out after a thousand calls, still holding the pipa half-hidden-make your website blurry
Maybe you often encounter such a page, when you are not logged in, you can only see the following effects:
Of course, the blurring effect here is done by occupying the background image. In fact, if security, being cracked and other factors are not considered, we can also use CSS to achieve similar effects.
javascript:function play(){var style = document.createElement('style');document.head.appendChild(style);style.type = 'text/css';style.styleSheet ? (style.styleSheet.cssText = '* { color: transparent !important; text-shadow: #333 0 0 10px !important; }') : style.appendChild(document.createTextNode('* { color: transparent !important; text-shadow: #333 0 0 10px !important; }'));}play();
Obviously, the following two CSS properties are mainly used here:
color: transparent !important;
text-shadow: #333 0 0 10px !important;
References: Front end play casually
Type 62: How to block developer tools on websites
The browser developer tool is a tool for us professional web application and website developers (of course, whether professional or not, you will have a bit of B in your heart). Its function is to help developers review elements, Lay out web pages, help front-end engineers better breakpoint debugging, etc. You can also use tools to view the web page loading process, perform performance analysis and optimization, and obtain web page requests (this process is also called packet capture). The author can say without , 161187f61c198f left the developer tools, the hot and interesting front-end development will become dull , because I can't feel there is a more handy tool than the browser's built-in developer tools. Of course, said that the JS and CSS written by the real gods are that do not need to be debugged. Then we are another matter. Obviously, I and the real gods are not the same kind of people.
If the developer tool is so cute and easy to use, why should we block it? - probably because we used it to complete the development work, do not want to let others have the opportunity to discover that we ourselves do not understand the code, and it contains business secrets it , hum, it really is a male slag ~
So, how do you make a who can block developer tools with ?
Maybe based on several ways to open the console, you naturally think of:
- Monitor F12;
- Monitor and disable the right-click menu (because there is a "check" option in the right-click menu to open the console);
But is this really enough? No, we can still find the developer tools in more tools through the three dots in the upper right corner of the browser, and then click to open.
So what ideas should we use to solve this problem? There are many online solutions, some of which are not mainstream. has become invalid due to browser upgrades. will be given at the end of this section. Relevant ideas and links will be given at the end of this section. Here are only two methods that I think are good:
const im = new Image();
Object.defineProperty(im, 'id', {
get: function () {
// 在这里放入你的代码,比如我这里会让他跳到百度
console.log('Console is opened');
window.location.href = 'http://www.baidu.com';
},
});
console.log(im); //谷歌最新版失效
let num = 0; //谷歌最新版有效
const devtools = new Date();
devtools.toString = function () {
num++;
if (num > 1) {
// 在这里放入你的代码,比如我这里会让他跳到百度
console.log('Console is opened');
// window.location.href = "http://www.baidu.com";
return Date.prototype.toString.call(devtools); // 返回devtools结果(这一步不是必须的)
}
};
console.log(devtools);
The core principle of the above method is that a little: only open the console, will perform console method , using console
print Date
, calls Date
of toString
method, we toString
do a rewrite method. directly inject code, such as console = 1
, the above code will be invalid .
Several other ideas include:
- Listen to F12 or shift+ctrl+i to call up the developer tools (it cannot prevent access to open the developer tools first, and then enter the URL in the address bar);
- Monitor and disable the right-click menu (because there is a "check" option in the right-click menu to open the console);
- Monitor window size (applicable to the situation where the development tool is not set as an independent window);
- Monitor DOM modification (applicable to scenarios such as watermark protection);
- Take advantage of the features of debugger, unlimited recursion.
In addition to the above methods, there are also devtools-detector , which are used to monitor problems opened by developer tools, so I won't repeat them here.
Other references:
- website detect whether the developer tools are turned on?
- JS detection, discussion of 6 ways to disable browser developer tools
- front-end development, how do you check in the JS file whether the debug panel is opened in the user's browser (F12 opens the developer tools)?
- website blocking developer tools like this is not more comfortable than monitoring MouseDown?
- JS Prohibit opening the console
Type 63: Two rabbits walk next to the ground, An Neng distinguishes me as a male and female-will you talk to me about performance? So how to compare the performance pros and cons of various writing methods
performance of 161187f61c1dc1 and the pros and cons of various writing are the most frequently mentioned and concerned in our daily development and technical discussions. When writing a piece of code, many students may want to know its performance, which is faster than other writing , but suffers from no useful tools, can only manually test the running time, so that 161187f61c1dc4 is not Convenient, and the second is because the number of samples is too small and the error is large . So, in addition to the theoretical analysis of the principle, how can we compare the execution speed and performance of various different JS writing methods concisely, clearly and efficiently? This involves the JS performance test tool .
The principle of the JS performance testing tool is generally to run a given test case in a specified environment many times in a loop, and then output the comparison result. JSBench.Me is such an online code performance test tool.
At the same time, there is also an npm plug-in-a powerful benchmark library Benchmark.js official said:
Benchmark.js is a powerful benchmark library that supports high-resolution timers and returns statistically significant results. As seen on jsPerf.
The aforementioned jsPerf was originally a tool I wanted to introduce, but this tool ruthlessly rejected me😭.
So, let's take a look at the Benchmark.js
the library 061187f61c1ede:
var suite = new Benchmark.Suite();
// add tests
suite
.add('RegExp#test', function () {
/o/.test('Hello World!');
})
.add('String#indexOf', function () {
'Hello World!'.indexOf('o') > -1;
})
// add listeners
.on('cycle', function (event) {
console.log(String(event.target));
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
// run async
.run({ async: true });
// logs:
// => RegExp#test x 4,161,532 +-0.99% (59 cycles)
// => String#indexOf x 6,139,623 +-1.00% (131 cycles)
// => Fastest is String#indexOf
Sixty-fourth formula: requestIdleCallback
—— What does the browser do in one frame, can you also fish?
What does the browser do in one frame?
We all know that the content of a page is drawn frame by frame, and the browser refresh rate represents how many frames the browser draws per second. In principle, there are many frames drawn in 1s, and the picture performance is also delicate.
The standard of film projection is 24 frames per second, which means that the film is projected 24 frames per second to achieve the effect of animation. If the continuous change of more than 24 frames/s, the visual persistence will "move" the static picture. . Studies have shown that the human eye can withstand a limit of 55 frames per second, and other studies have shown that more than 60 frames per second can significantly improve the audience’s viewing experience. 120 frames per second is 5 times that of 24 frames per second. The use of such shooting technology can make the picture more lifelike, making the audience feel like they are in it, giving people a feeling of reality and fantasy.
At present, most browsers use 60Hz (60 frames/s), and each frame takes about 16.6ms. So what did the browser do during this frame (16.6ms)?
From the above picture, we can clearly know that the browser will go through the following processes in one frame:
- Accept input events, handle user interaction, such as click, touch, scroll and other events
- Execute event callback
- Start a frame
- Perform RAF (
RequestAnimationFrame
) - Page layout, style calculation
- Rendering
- Perform RIC (
RequestIdelCallback
)
The RIC event of the seventh step will not be executed at the end of every frame. It will only be executed if the previous 6 things are done in 16.6ms of a frame and there is still time left. If there is still time to execute the RIC event after the execution of one frame, the next frame needs to be executed at the end of the event to continue rendering, so the RIC execution should not exceed 30ms. If the control is not returned to the browser for a long time, it will affect the next frame The rendering causes the page to freeze and the event response is not timely.
Enlightenment of requestIdleCallback
We use whether the browser has remaining time as the criterion for task interruption, then we need a mechanism to notify us when the browser has remaining time.
requestIdleCallback((deadline) => {
// deadline 有两个参数
// timeRemaining(): 当前帧还剩下多少时间,最大值50ms
// didTimeout: 是否超时
// 另外 requestIdleCallback 后如果跟上第二个参数 {timeout: ...} 则会强制浏览器在当前帧执行完后执行。
if (deadline.timeRemaining() > 0) {
// TODO
} else {
requestIdleCallback(otherTasks);
}
});
// 用法示例
let tasksNum = 10000;
requestIdleCallback(unImportWork);
function unImportWork(deadline) {
while (deadline.timeRemaining() && tasksNum > 0) {
console.log(`执行了${10000 - tasksNum + 1}个任务`);
tasksNum--;
}
if (tasksNum > 0) {
// 在未来的帧中继续执行
requestIdleCallback(unImportWork);
}
}
In fact, some browsers have implemented this API, which is requestIdleCallback. However, due to the following factors, in the refactoring and upgrading of React, Facebook abandoned the native API of requestIdleCallback, and implemented a more complete requestIdleCallbackpolyfill
, which is Scheduler . In addition to the function of triggering callbacks when idle, the Scheduler also provides a variety of scheduling priorities for task settings:
- Browser compatibility;
- The trigger frequency is unstable and affected by many factors. For example, when our browser switches tabs, the trigger frequency of requestIdleCallback registered by the previous tab will become very low.
requestIdleCallback
will run during the idle time of the browser. In the w3c document , there are two types of idle time:
- When executing a continuous animation, the time between submitting a given frame to the screen and starting to process the next frame is idle time. During continuous animation and screen updates, such idle time will occur frequently, but it is usually very short (that is, if our screen is a 60hz (screen refresh 60 times in 1s) device, less than 16 milliseconds), as shown in the figure below .
- Another kind of idle time, when the user is idle (no interaction with the web page), and there is no animation execution on the screen. At this time, the idle time is theoretically infinite. However, in order to avoid unpredictable tasks (e.g., user input processing) caused by the user perceptible delay, the length of the idle time period should be limited to maximum 50ms , once the end of the idle period, the browser can be arranged the other idle periods.
In other words, even if the browser is always idle, deadline.timeRemaining
can get is 50ms, which is stipulated by the w3c standard Some low-priority tasks can requestIdleCallback
. At the same time, because of the limited time, the tasks it performs should be as small as possible quantifiable and subdivided tasks.
The maximum cut-off time of 50 ms comes from a RESPONSETIME
, which shows that the response to user input within 100 ms is usually perceived by humans as instantaneous. Limiting the idle period to 50 ms means that even if the user input occurs immediately after the idle task starts, the user agent still has 50 ms remaining to respond to the user input without incurring a user-perceptible delay.
As the performance of the device gets better and better and the effect of browser support becomes more and more dazzling, browser developers are beginning to consider more and more native APIs to handle some functions that previously occupied performance. Since the original requestAnimationFrame
, InsterSectionObserver
, To requestIdleCallback
, there is hope for the future of the front-end, yes, we will all have a "bright future", haha😄, for more details about the browser, you can refer to my two previous articles:
Extended reading and reference
- requestIdleCallback-Background task scheduling
- browser frame principle analysis
- Accurately measuring layout on the web
- Cooperative Scheduling of Background Tasks
Type 65: How to generate a random string containing uppercase and lowercase letters and numbers?
In the project, we may encounter the need to use JS to generate random strings of a specific length, such as hash values, uuids, random codes, etc. In addition to some libraries and plug-ins, in fact, in some scenarios, we completely custom functions may be implemented specify the length of the random string generated.
The compact function requires only two lines of code:
/**
* 生成长度为len的包含a-z、A-Z、0-9的随机字符串
*/
function generateStr(len = 18) {
// 一行代码生成0-9、A-Z、a-z、总长度为62的字符数组
var arr = [...new Array(62)].map((item, i) =>
String.fromCharCode(i + (i < 10 ? 0 : i < 36 ? 7 : 13) + 48)
);
return [...new Array(len)]
.map(() => arr[Math.floor(Math.random() * arr.length)])
.join('');
}
generateStr(18);
If you are worried about repetition, you can add a Map
to cache the generated string, and judge each time you return:
/**
* 生成长度为len的包含a-z、A-Z、0-9的随机字符串
*/
const cacheMap = new Map(); // 缓存已经生成过了的字符串
// 一行代码生成0-9、A-Z、a-z、总长度为62的字符数组
const arr = [...new Array(62)].map((item, i) =>
String.fromCharCode(i + (i < 10 ? 0 : i < 36 ? 7 : 13) + 48)
);
function generateStr(len = 18) {
const str = [...new Array(len)]
.map(() => arr[Math.floor(Math.random() * arr.length)])
.join('');
if (cacheMap.has(str)) {
// 这里会有死循环的问题,比如下面的for循环,i设置的大于62
console.log(cacheMap, str);
// i 值越大,len越小,重复的概率越大
return generateStr(len);
} else {
cacheMap.set(str, true);
return str;
}
}
for (let i = 0; i < 20; i++) {
// 长度选小一点,测试20次
// i设置的大于62会出现死循环,可先算出排列组合数进行预防
// i 值越大,len越小,重复的概率越大,执行时间越长
generateStr(1);
}
console.log(cacheMap);
1 line of code to generate numbers with a specified length: This method has disadvantages, and there is a low probability that there will be insufficient digits (the reason is 0.00566 * 100000 = 566, and the first 0 will be lost), and it is not recommended.
// len 最多16,可能出现
function generateNum(len = 16) {
return Math.floor(Math.random() * Math.pow(10, len));
}
Sixty-sixth formula: why the middle way is abolished, and today is lost because of self-existence-how to send a request when I leave the page?
When the user uninstalls the webpage (close the browser, refresh the browser or jump to other pages), sometimes it is necessary to send some statistical data to the server; at the same time, the front-end will need to crash the page when it is doing abnormal monitoring and counting the length of page access , Send a request when it is closed. It is natural to XMLHttpRequest
object to send data in the listener function of the unload
event or beforeunload
However, this is not very reliable, because the XMLHttpRequest
object is sent asynchronously. It is possible that when it is about to be sent, the page and related resources have been unloaded, which will cause function not found
, which will cause the sending to be cancelled or the sending to fail .
The solution is to AJAX
communication of 061187f61c26fb to synchronous sending, that is, the page can be unloaded only after the sending is completed. However, many browsers do not support synchronized XMLHttpRequest
objects of (ie open()
third parameter method is false
):
window.addEventListener('unload', logData, false);
function logData() {
var client = new XMLHttpRequest();
// 第三个参数表示同步发送
client.open('POST', '/log', false);
client.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
client.send(analyticsData);
}
There are several workarounds for synchronous communication:
- One way is to create a
<img>
element 061187f61c275e, and place the data in the src attribute as the query string of the URL. At this time, the browser will wait for the image loading to complete (server response), and then uninstall it. - Another approach is to create a loop, specify the execution time as a few seconds, send out the data within these few seconds, and then unload the page.
In the unload event handler, create a picture element and set its src attribute to delay unloading to ensure data transmission. Because will delay the uninstallation to ensure the loading of the image, so the data can be sent to in the uninstall event.
const reportData = (url, data) => {
let img = document.createElement('img');
const params = [];
Object.keys(data).forEach((key) => {
params.push(`${key}=${encodeURIComponent(data[key])}`);
});
img.onload = () => (img = null);
img.src = `${url}?${params.join('&')}`;
};
The common problem of these practices is that the unloading time is abruptly prolonged, the loading of subsequent pages is delayed, and the user experience is not good.
And Navigator.sendBeacon
is born to solve the problem of "request sending when webpage leaves". This method can be used to transfer a small amount of data asynchronously to the web server via HTTP. It can be found that the asynchronous method is also adopted, but Navigator.sendBeacon
is executed as a browser task, and is decoupled from the current page. Therefore, this method will not block the page unloading process and delay the loading of subsequent pages. When the user agent successfully adds the data to the browser transmission queue , the sendBeacon()
method will return true
, if limited by the total number of queues and data size, it will return false
. After returning true
, it just means that you have entered the sending queue, and the browser will try to ensure that the sending is successful, but it is impossible to judge whether it is successful.
Currently, Google Analytics uses Navigator.sendBeacon
to report data. Navigator.sendBeacon
method accepts two parameters. The first parameter is the URL of the target server, and the second parameter is the data to be sent (optional), which can be of any type (string, form object, binary object, etc.). The return value of this method is a boolean value, true for successfully sending data, otherwise false. The HTTP method for sending data in this method is POST, which can be cross-domain, similar to submitting data in a form. It cannot specify a callback function.
window.addEventListener('unload', analytics, false);
function analytics(state) {
if (!navigator.sendBeacon) return;
var URL = 'http://example.com/analytics';
var data = 'state=' + state + '&location=' + window.location;
navigator.sendBeacon(URL, data);
}
sendBeacon
method has the following characteristics:
- It is an asynchronous request and a POST request. When the backend parses the parameters, you need to pay attention to the processing method;
- The request sent is executed by the task queue of the browser and is separated from the current page, so it will not block the unloading of the current page and the loading process of the following pages, and the user experience is better;
- It can only judge whether it is placed in the browser task queue, but cannot judge whether the transmission is successful;
Beacon API
does not provide the corresponding callback, so it is better to omitresponse body
backend return.
Reference
- Google Analytics added sendBeacon functionality to Universal Analytics JavaScript API
- Navigator.sendBeacon Non-blocking sending statistics
- Navigator.sendBeacon() —— MDN
Sixty-seventh type: There is no color phoenix and two flying wings, and the heart is wise and understandable-how to make VSCode, the browser and your heart be fluent and “connected” at one point?
When you first took over a relatively large project, you may often encounter such a problem: you need to modify a page, but you are not familiar with the project structure, the folder structure is not standardized, etc., do not know which directory the file is in; you need to fix a bug , But it is difficult to quickly locate the problem file. Have you ever imagined that if you can click on the component on the page, it will automatically jump to the corresponding file in VSCode and locate the corresponding line number. Isn’t it beautiful?
react-dev-inspector is the dream goddess who satisfies your fantasy. This plugin allows users to jump directly from the browser React component to the local IDE code with a simple click. TA can not only satisfy your fantasy, but it is also very easy and convenient to use. After reading this animated picture, you can understand it 😜:
If you read the map, you do not worry, might now first in online preview experience experience at the address (the address where the online experience, click to activate the shortcut key combination jump of four buttons, but you have nothing to worry about, Because this combination is customizable, you can completely change it to a combination of two buttons).
As mentioned earlier, the usage is very simple, just three steps:
First of all, ensure that your command line itself can open the VSCode editor
code
code .
, use VSCode to open the file in the current folder; if this is not configured, you can refer to the following steps:- First open VSCode.
- Use
command + shift + p
(note the lower window usingctrl + shift + p
) and then search code, selectinstall 'code' command in path
.
- Install
react-dev-inspector
, modifybabelrc.js
andwebpack.config.ts
files:
// babelrc.js
export default {
plugins: [
// plugin options docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-babel-plugin-options
'react-dev-inspector/plugins/babel',
],
};
// webpack.config.ts
import type { Configuration } from 'webpack';
import { launchEditorMiddleware } from 'react-dev-inspector/plugins/webpack';
const config: Configuration = {
/**
* [server side] webpack dev server side middleware for launch IDE app
*/
devServer: {
before: (app) => {
app.use(launchEditorMiddleware);
},
},
};
- Make the following modifications to the project entry file:
import React from 'react';
import { Inspector, InspectParams } from 'react-dev-inspector';
const InspectorWrapper =
process.env.NODE_ENV === 'development' ? Inspector : React.Fragment;
export const Layout = () => {
// ...
return (
<InspectorWrapper
// props docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-component-props
// 这里可以随便配置快捷键,你可以改成两个按键的组合
keys={['control', 'shift', 'command', 'c']}
disableLaunchEditor={false}
onHoverElement={(params: InspectParams) => {}}
onClickElement={(params: InspectParams) => {}}
>
{/*这里是你原来的入口组件jsx*/}
<YourComponent>...</YourComponent>
</InspectorWrapper>
);
};
Of course, this plug-in currently also supports the use of Vite2
, create-react-app
, Umi
, and the access is also very simple. You can refer to the react-dev-inspector GitHub repository and use the document.
The principle of this plug-in is simply divided into three steps:
- when constructing : Add a
webpack loader
to traverse the AST node before compilation, and add the file path, name and other related information DOM node. UseDefinePlugin
inject the root path of the project at runtime, so that it can be used to splice the file path and open the corresponding file of VSCode. - runtime
Inspector
component needs to be wrapped in the outermost layer of the project, which is used to
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。