当前位置 : 首页 » 文章分类 :  开发  »  JavaScript

JavaScript

JavaScript 学习笔记

在线执行代码
https://tool.lu/coderunner/

廖雪峰JavaScript教程
https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000

Mozilla MDN JS教程
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript


Page Visibility API​​ 页面可见性API

JavaScript 中可通过 ​​Page Visibility API​​ 精确检测页面是否处于前台(用户可见)

visibilityState 页面可见状态

document.visibilityState ​返回当前页面的可见状态

  • visible 页面内容至少部分可见(例如标签页在前台、窗口未被最小化)。
  • hidden 页面内容对用户完全不可见(如标签页切换到后台、窗口最小化、屏幕锁定等)。

​visibilitychange 页面可见状态变化事件

​visibilitychange 事件​​:当页面可见状态变化时触发,例如用户切换标签页、最小化窗口等

js 代码示例:

// 监听可见性变化
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') {
    console.log('页面处于前台'); // 用户正在查看当前页面
  } else {
    console.log('页面处于后台'); // 用户离开页面
  }
});

// 直接获取当前状态
const isForeground = document.visibilityState === 'visible';
console.log(`当前是否前台: ${isForeground}`);

页面可见状态 visibilityState 与 窗口焦点状态 onfocus/onblur

假如有2块屏幕,网站页面在第二块屏幕的前台页面可看到,但鼠标在第一个屏幕上,那么 visibilityState 可见状态是什么?
答:visible
多显示器场景,如果页面所在的浏览器标签页处于​​激活状态​​(即该标签页是当前浏览器的前台标签),即使系统焦点在另一个显示器上,该页面仍然被认为是可见的,即 visibilityState === 'visible'

即使页面被其他窗口​​部分覆盖​​,只要浏览器窗口未被最小化且标签页在前台,visibilityState 状态仍为 visible

可见性状态 visibilityState 与 窗口焦点状态 window.onfocus/onblur 无关,只要页面是浏览器的激活页面 visibilityState 就是 visible,无论窗口是否在焦点上。

window.onfocus = () => console.log("窗口聚焦(前台)");
window.onblur = () => console.log("窗口失焦(后台)");

实例:页面切换时暂停视频

const video = document.getElementById('myVideo');
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    video.pause(); // 离开页面时暂停
  } else {
    video.play(); // 返回页面时继续
  }
});

SharedWorker

SharedWorker​​ 是 JavaScript 中 Web Workers 的一种特殊类型,允许多个浏览器上下文(如不同标签页、窗口 或 iframe)​​共享同一个后台线程​​。它解决了传统 Dedicated Worker(专用 Worker)无法跨页面共享的问题。

1、多页面共享​​
同一域名下的不同页面访问相同脚本路径时,共享同一个 Worker 实例。
2、基于端口的通信​
通过 MessagePort 对象建立连接(每个连接对应一个独立的 port)。
3、独立生命周期
Worker 在所有连接关闭后自动终止,不受单个页面关闭影响。
4、线程安全通信​
使用结构化克隆算法传输数据,确保线程安全。


创建 SharedWorker 实例

https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker

var myWorker = new SharedWorker(scriptURL);
var myWorker = new SharedWorker(scriptURL, name);
var myWorker = new SharedWorker(scriptURL, options);

参数:
scriptURL 字符串,表示 worker js 脚本的URL,必须同源
name 可选,SharedWorker 名称,可方便调试
options 可选,额外属性

  • type: 字符串,classic 或 module,默认是 classic
  • name: 字符串,用于命名worker,可用于解决同一脚本不同worker实例的区分
  • credentials: 字符串,凭据选项,可取值 ‘omit’, ‘same-origin’, ‘include’,默认值 omit

返回值:返回一个 SharedWorker 对象,包含以下重要属性:

  • port 一个 MessagePort 对象,用于和 worker 进行通信。
  • onerror 错误事件处理器。

不同页面如果使用相同的 scriptURL 和相同的 name(如果提供了),则会共享同一个 worker 实例。如果 name 不同,即使同一个脚本URL也会创建不同的 worker 实例


self.onconnect

在 Worker 线程内部,即 shared.js 脚本内,通过 self.onconnect 处理 主页面/主线程 的连接事件
事件对象为 MessageEvent,其 ports 属性是一个数组,但通常只有一个端口,即事件对象的第一个端口 e.ports[0]
在 worker 线程内部,我们可以通过获取到的端口(port)来设置 onmessage 事件处理函数,进行双向通信。


MessagePort

https://developer.mozilla.org/en-US/docs/Web/API/MessagePort

port.start() 开始接收消息。如果使用 addEventListener 来监听消息,则必须调用 start() 方法。如果使用 onmessage 则不需要。
port.close() 关闭端口,断开与 worker 的连接。
port.onmessage 设置消息事件处理函数(当 worker 通过该端口发送消息时触发)。
port.onmessageerror 处理消息解析错误事件。

port.postMessage(message, transferList) 向 worker 发送消息。

  • message 要传递的数据,可以是任意结构化克隆算法支持的类型。
  • transferList 可选,一个可转移对象的数组,如 ArrayBuffer 等。

查看 SharedWorker


通过 SharedWorker 在多页面间通信示例

SharedWorker 线程脚本 shared.js

// 保存所有页面的通信端口
const connectedPorts = [];

// 处理来自页面的连接请求
self.onconnect = (e) => {
  // 从事件对象获取通信端口
  const port = e.ports[0];
  
  // 添加到连接列表
  connectedPorts.push(port);
  
  // 处理来自页面的消息
  port.onmessage = (e) => {
    const message = e.data;
    
    // 广播消息给所有连接页面
    broadcast({
      type: message.type,
      username: message.username,
      text: message.text,
      timestamp: new Date().toISOString()
    });
  };

  // 发送欢迎消息
  port.postMessage({
    type: 'system',
    text: '连接已建立!当前用户数: ' + connectedPorts.length
  });
  
  // 监听端口关闭
  port.addEventListener('close', () => {
    removePort(port);
  });
};

// 广播消息给所有连接的页面
function broadcast(message) {
  connectedPorts.forEach(port => {
    port.postMessage(message);
  });
}

// 移除断开连接的端口
function removePort(port) {
  const index = connectedPorts.indexOf(port);
  if (index !== -1) {
    connectedPorts.splice(index, 1);
    
    // 通知所有用户更新在线人数
    broadcast({
      type: 'system',
      text: `用户已断开。当前用户数: ${connectedPorts.length}`
    });
  }
}

主页面/主线程 中的脚本:

<script>
  // 1. 创建 SharedWorker
  const worker = new SharedWorker('shared.js');
  const port = worker.port;
  
  // 2. 启动通信端口
  port.start();
  
  // 3. 接收来自 Worker 的消息
  port.onmessage = (e) => {
    const message = e.data;
    displayMessage(message);
  };
  
  // 4. 发送消息
  document.getElementById('sendBtn').addEventListener('click', () => {
    const username = document.getElementById('username').value;
    const text = document.getElementById('messageInput').value;
    
    if (text.trim()) {
      port.postMessage({
        type: 'message',
        username: username,
        text: text
      });
      
      document.getElementById('messageInput').value = '';
    }
  });
  
  // 5. 显示消息
  function displayMessage(message) {
    const messagesEl = document.getElementById('messages');
    const messageEl = document.createElement('div');
    
    messageEl.className = message.type === 'system' ? 
      'message system-message' : 'message';
    
    messageEl.innerHTML = message.type === 'system' ?
      `<em>${message.text}</em>` :
      `<strong>${message.username}:</strong> ${message.text}`;
    
    messagesEl.appendChild(messageEl);
    messagesEl.scrollTop = messagesEl.scrollHeight;
  }
  
  // 6. 页面关闭时通知 Worker
  window.addEventListener('beforeunload', () => {
    port.postMessage({ type: 'close' });
  });
</script>

变量

全局变量

全局变量 (Global Variables)
定义:在函数或代码块 ​​外部​​ 声明的变量(使用 var、let、const),或未声明直接赋值的变量
作用域​​:整个脚本可用,包括所有函数和代码块。
生命周期​​:页面关闭时销毁。
风险​​:过度使用会导致命名冲突和代码污染(例如第三方库同名变量覆盖)。

var globalVar = "全局变量"; // 全局变量
let globalLet = "也是全局变量"; // 全局作用域,但不在 window 对象上
unDeclared = "未声明的变量"; // 自动成为全局变量(不推荐!)

局部变量

局部变量 (Local Variables)

函数作用域 (Function Scope):用 var 在 ​​函数内部​​ 声明的变量

function example() {
  var localVar = "局部变量"; // 仅在函数内有效
  console.log(localVar); // ✅
}
console.log(localVar); // ❌ 报错:未定义

块级作用域 (Block Scope - ES6):用 let/const 在 ​​{} 代码块内​​(如 if、for)声明的变量

if (true) {
  let blockLet = "块级变量"; 
  const blockConst = "块级常量";
}
console.log(blockLet); // ❌ 报错:未定义

在全局作用域中声明变量可以省略 var 关键字。
默认非严格模式下,在函数体内声明变量时如果不使用 var 关键字会隐式声明为全局变量,即使该语句是在一个 function 内,当该 function 被执行后就变成了全局变量

variable = 'global';

function checkVariable() {
    variable = 'local';
    console.log(variable); // local
    myVariable = 'local';
    console.log(myVariable); // local
}

checkVariable();

console.log(variable); // local
console.log(myVariable); // local

所以:
声明局部变量一定要使用 var 关键字,使用 var 关键字声明变量时,变量会自动添加到距离最近的可用环境中。如果没有写 var, 变量就会暴露在全局上下文中, 这样很可能会和现有变量冲突

编写可维护的JavaScript-全局变量
https://segmentfault.com/a/1190000021219901


use strict 严格模式

JavaScript 的 ​​严格模式(Strict Mode)​​ 是 ECMAScript 5(ES5)引入的重要特性,它通过更严格的语法和运行时规则来约束代码行为,帮助开发者避免常见的错误,提升代码的安全性和可维护性。

在脚本或函数顶部添加 "use strict"; 即可启用严格模式

// 整个脚本启用
"use strict";
let x = 10; // 正确

// 单个函数启用
function strictFunc() {
  "use strict";
  y = 20; // 报错:未声明变量
}

字符串

模板字符串

模板字符串使用反引号 “" (键盘左上角波浪线下面的字符) 来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法( ${expression}` )的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来。
在模版字符串内使用反引号时,需要在它前面加转义符(\)

如果有很多变量需要连接,用+号就比较麻烦。ECMAScript 6(ES 6) 新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:
例如拼接当前页面的链接:

var pageRef = `<a href="${window.location.protocol}//${window.location.host}${window.location.pathname}">当前页面链接</a>`
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);

字符串判空

if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
  var variable2 = variable1;
}

字符串等值比较

JavaScript 有两种相等运算符:
1、一种是完全向后兼容的,标准的 ==,如果两个操作数类型不一致,它会在某些时候自动对操作数进行类型转换,考虑下面的赋值语句:

var strA = "i love you!";
var strB = new String("i love you!");

这两个变量含有相同的字符序列,但数据类型却不同,前者为string,后者为object,在使用 == 操作符时,JavaScript 会尝试各种求值,以检测两者是否会在某种情况下相等。所以下面的表达式结果为 true: strA == strB。

2、第二种操作符是”严格”的 ===,它在求值时不会这么宽容,不会进行类型转换。所以表达式 strA === strB 的值为false,虽然两个变量持有的值相同。
有时代码的逻辑要求你判断两个值是否不相等,这里也有两个选择:”!=”和严格的”!==”,它们的关系就类似于”==”和”===”。

“==”和”!=”在求值时会尽可能地寻找值的匹配性,但你可能还是想在比较前进行显式的类型转换,以”帮助”它们完成工作。比如,如果想判断一个用户的输入值(字符串)是否等于一个数字,你可以让”==”帮你完成类型转换:

if(document.form1.txtAge.value == someNumericVar) {
   …
}

也可以提前转换:

if(parseInt(document.form1.txtAge.value) == someNumericVar) {
  …
}

字符串大小比较

javascript 字符串在进行大于(小于)比较时,会根据第一个不同的字符的 ascii 值码进行比较。
当数字(number)与字符串(string)进行比较大小时,JavaScript 会首先将其转化为数字(number)再判定大小。

var numbers = ['APP_20221219', 'APP_20221221', 'APP_20221227'];
numbers.forEach((item, index) => {
    if (item < 'APP_20221224') {
        console.log(item)
    }
});

结果
APP_20221219
APP_20221221


substring()

substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。
str.substring(indexStart[, indexEnd])
indexStart 需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母。
indexEnd 可选。一个 0 到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。


slice() 字符串切片

slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
参数:
start 必须。 要抽取的片断的起始下标,第一个字符位置为 0。如果为负数,则从尾部开始截取。
end 可选。 紧接着要截取的片段结尾的下标。若未指定此参数,则要提取的子串包括 start 到原字符串结尾的字符串。如果该参数是负数,那么它规定的是从字符串的尾部开始算起的位置。

slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。


startsWith() 以开头

startsWith() 方法用来判断当前字符串是否以另外一个给定的子字符串开头,并根据判断结果返回 true 或 false。

const str1 = 'Saturday night plans';

console.log(str1.startsWith('Sat'));
// expected output: true

console.log(str1.startsWith('Sat', 3));
// expected output: false

String.prototype.startsWith()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith


includes() 是否包含子串

includes() 方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false。
includes() 方法是区分大小写的。

var string = "foo", substring = "oo";
console.log(string.includes(substring));

String.prototype.includes()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/includes


atob() base64 解码

var b64s = ['dGhpcyBpcyBtYXNpa2tr', 'dGhpcyBpcyBkZGRkZA=='];
b64s.forEach((item, index) => {console.log(atob(item))});

How can you encode a string to Base64 in JavaScript?
https://stackoverflow.com/questions/246801/how-can-you-encode-a-string-to-base64-in-javascript


数组

forEach() 遍历

Array.prototype.forEach()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

forEach() 方法是一个迭代方法。它按索引升序地为数组中的每个元素调用一次提供的 callbackFn 函数。

语法:

forEach(callbackFn)
forEach(callbackFn, thisArg)

参数:
callbackFn 是为数组中每个元素执行的函数:

  • element 必需,数组中正在处理的当前元素。
  • index 可选,数组中正在处理的当前元素的索引。
  • array 可选,调用了 forEach() 的数组本身。

thisArg 可选。执行 callbackFn 时用作 this 的值。如果这个参数为空, “undefined” 会传递给 “this” 值。
最终由 callbackFn 观察到的 this 值根据通常的规则 确定:如果 callbackFn 是非严格模式(译注:正常模式/马虎模式),原始 this 值将被包装为对象,并将 undefined/null 替换为 globalThis。对于使用 箭头函数 定义的任何 callbackFn 来说,thisArg 参数都是无关紧要的,因为箭头函数没有自己的 this 绑定。

语法形式

// 箭头函数
forEach((element) => { /* … */ })
forEach((element, index) => { /* … */ })
forEach((element, index, array) => { /* … */ })

// 回调函数
forEach(callbackFn)
forEach(callbackFn, thisArg)

// 内联回调函数
forEach(function(element) { /* … */ })
forEach(function(element, index) { /* … */ })
forEach(function(element, index, array){ /* … */ })
forEach(function(element, index, array) { /* … */ }, thisArg)

例1,forEach 遍历数组对象

var numbers = ['hello', 'my', 'world'];
numbers.forEach((item, index) => {console.log(item)});

map()

Array.prototype.map()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

例如:

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
var array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

对 b64s 做流式处理:

var b64s = ['app1@dGFibGUxL3RoaXMgaXMgbWFzaWtraw==', 'app2@dGFibGUyL3RoaXMgaXMgZGRkZGQ='];
b64s
    .map((item, index) => {
        return item.substring(item.indexOf('@') + 1)
     })
    .map((item, index) => {
        return atob(item);
     })
    .forEach((item, index) => {
        var tabname = item.substring(0, item.indexOf('/'));
        var str = item.substring(item.indexOf('/')+1);
    console.log(tabname, str);
     });

reduce()

Array.prototype.reduce()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

reduce() 方法对数组中的每个元素执行一个传入的 reducer 函数(升序执行),将其结果汇总为单个返回值。

语法:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

callback 执行数组中每个值的函数,包含四个参数:

  • accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
  • currentValue 数组中正在处理的元素。
  • currentIndex 可选 数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则为1。
  • array 可选 调用reduce()的数组

initialValue 可选 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
返回值 函数累计处理的结果

回调函数第一次执行时,accumulator 和 currentValue 的取值有两种情况:如果调用 reduce() 时提供了 initialValue,accumulator 取值为 initialValue,currentValue 取数组中的第一个值;如果没有提供 initialValue,那么 accumulator 取数组中的第一个值,currentValue 取数组中的第二个值。

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

例如

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15

js求集合并集交集差集

a = [1, 2, 3];
b = [2, 4, 5];

// 并集
let union = a.concat(b.filter(v => !a.includes(v))) // [1,2,3,4,5]
console.log(union)

// 交集
let intersection = a.filter(v => b.includes(v)) // [2]
console.log(intersection)

// 差集
let difference = a.concat(b).filter(v => !a.includes(v) || !b.includes(v)) // [1,3,4,5]
console.log(difference)

js数组元素去重

a = [1,2,2,3,4];

b = Array.from(new Set(a));
console.log(b);

js数组判空

var arr = [];
if(Array.isArray(arr) && arr.length === 0){
    console.log('是空数组');
}

布尔值

js 中 ! 用于 bool 值取反

!true   // → false
!false  // → true
!"abc"  // → false(非空字符串为真,取反后为假)
!null   // → true(null 为假,取反后为真)
!0      // → true(0 为假,取反后为真)

!! 将一个值强制转换为布尔值(true 或 false)的技巧:

!!null        // → false(没有 token)
!!undefined   // → false(没有 token)
!!""          // → false(空 token)
!!"abc123"    // → true(有效 token)
!!0           // → false(异常数值)

对象

判断对象是否包含某个key

1、in 运算法
如果指定的属性在指定的对象或父类中,则in 运算符返回true

if ( !'WebSocket' in window) {
}

2、hasOwnProperty
返回一个布尔值,指示对象自身属性是否有指定的属性
和in不同,会忽略继承到的属性
即使属性的值是null,undefined,只要属性存在,hasOwnProperty依旧会返回true

if (!window.hasOwnProperty("WebSocket")) {
}
if (!window.WebSocket) {
}

图片

图片file转base64

const fileToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
};

fileToBase64(file).then((base64) => {
  console.log(base64);
});

Math 对象

random() 0-1间的随机数

Math.random() 返回介于 0(包含) ~ 1(不包含) 之间的一个随机数:


Number 对象

toString() 转化为字符串

number.toString(radix)
radix 可选。规定表示数字的基数,是 2 ~ 36 之间的整数。若省略该参数,则使用基数 10。
但是要注意,如果该参数是 10 以外的其他值,则 ECMAScript 标准允许实现返回任意值。
2 - 数字以二进制值显示
8 - 数字以八进制值显示
16 - 数字以十六进制值显示
36 - 基数 36 表示使用数字 0-9 和字母 a-z 来表示数字。


全局函数

encodeURIComponent()

可把字符串作为 URI 组件进行编码
该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

JSON.stringify() JSON序列化

将 JavaScript 值转换为 JSON 字符串

例如将一个 js 对象转为 json 串:

var person={firstname:"John", lastname:"Doe", id:5566};
console.log(JSON.stringify(person));

例如使用 Ajax 发送请求时,用 JSON.stringify() 将 变量 转为 json 串

var req = {"name":"name", "site":"http://www.masikkk.com"}
data: JSON.stringify(req)

JSON.parse() JSON反序列化

将一个 JSON 字符串转换为对象
JSON.parse(text[, reviver])
text:必需, 一个有效的 JSON 字符串。
reviver: 可选,一个转换结果的函数,将为对象的每个成员调用此函数。

const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);

window 对象(浏览器窗口)

Window
https://developer.mozilla.org/zh-CN/docs/Web/API/Window

所有浏览器对象的最顶层是 window 对象​​。它代表当前打开的浏览器窗口或标签页。
window 对象表示一个包含 DOM 文档的窗口,其 document 属性指向窗口中载入的 DOM文档 。
window 作为全局变量,代表了脚本正在运行的窗口,暴露给 Javascript 代码。

window 对象常用操作方法:
window.innerWidth 浏览器窗口的宽度(不包含工具栏) console.log(window.innerWidth)
window.innerHeight 浏览器窗口的高度(不包含工具栏) console.log(window.innerHeight)
window.open() 打开新浏览器窗口 window.open(“https://example.com")
window.close() 关闭当前窗口 window.close()
window.scrollTo() 滚动到指定位置 window.scrollTo(0, 500)
window.alert() 显示警告弹窗 window.alert(“警告信息”)
window.setTimeout() 设置延迟执行的定时器 setTimeout(() => {}, 1000)
window.setInterval() 设置周期性执行的定时器 setInterval(() => {}, 1000)

pageYOffset = scrollY 文档在垂直方向已滚动的像素值,文档从顶部开始滚动过的像素值
pageYOffset 属性是 scrollY 属性的别名
为了跨浏览器兼容,请使用 window.pageYOffset 代替 window.scrollY


window. 可省略

在浏览器环境中,全局变量和函数实际上是被添加到 window 对象上的。window 对象是浏览器中的全局对象,代表了当前浏览器窗口。
window 对象可以省略,如: alert() 等价于 window.alert()


document 对象

document 对象是 window 对象中最重要的二级对象,代表当前窗口加载的 HTML 文档
由于 window 对象可以省略,可以直接使用 document 对象,所以 window.document === document

// document 是 window 的属性
console.log(window.document === document); // true

// 实际用例
const title = document.title; // 获取页面标题
const bodyContent = document.body.innerHTML; // 获取 body 内容
const element = document.getElementById("myElement"); // 获取 DOM 元素

referrer 上一个页面url

document.referrer 返回 跳转或打开到当前页面 的页面的 URI
如果用户直接打开了这个页面(不是通过页面跳转,而是通过地址栏或者书签等打开的),则该属性为空字符串。


location 对象

Location 对象存储在 Window 对象的 Location 属性中,表示当前窗口中显示的文档的 Web 地址。
location 对象包含当前 URL 的信息并提供导航方法。
它的 href 属性存放的是文档的完整 URL,其他属性则分别描述了 URL 的各个部分。

当一个 Location 对象被转换成字符串,href 属性的值被返回。这意味着你可以使用表达式 location 来替代 location.href

Location
https://developer.mozilla.org/zh-CN/docs/Web/API/Location

主要属性 及 操作

console.log(window.location === location); // true

// location 的关键属性和方法
location.href;      // 完整 URL
location.protocol;  // http: 或 https:
location.host;      // 主机名和端口
location.hostname;  // 域名
location.pathname;  // 路径部分
location.search;    // 查询字符串 (?后部分)
location.hash;      // 哈希部分 (#后部分)

location.reload();  // 重新加载当前页面
location.assign("https://new-url.com"); // 导航到新页面
location.replace("https://new-url.com"); // 替换当前页面

href 页面完整url

protocol 协议

包含URL对应协议的一个DOMString,最后有一个”:”。

host 域名:端口号

对于没有端口的页面, host 等于 hostname
对于带端口的页面, host 包括整个 域名:端口, hostname只包含域名

hostname 不带端口号的域名

port 端口号

pathname url的path

包含URL中路径部分的一个DOMString,开头有一个“/“

search url的查询串

包含URL参数的一个DOMString,开头有一个“?”

hash 页内锚点

包含块标识符的DOMString,开头有一个“#”

origin 源信息(只读)

包含页面来源的域名的标准形式

通过location获取当前页面的url等信息

window.location.protocol: http:
window.location.host: localhost:4000
window.location.hostname: localhost
window.location.origin: http://localhost:4000
window.location.pathname: /article/JavaScript/
window.location.href: http://localhost:4000/article/JavaScript/

window.location与document.location

window 对象的 location 属性 等于 document 对象的 location 属性, 都是引用了 location 对象

window.location === document.location //true
document.location===location // true
window.location===location // true

navigator 提供浏览器和操作系统的信息

console.log(navigator.userAgent); 
// 示例输出: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..."

navigator.platform;  // 操作系统平台
navigator.language;  // 浏览器主语言
navigator.onLine;    // 是否联网
navigator.geolocation; // 获取位置信息接口

// 实际应用:检测浏览器功能
if ("geolocation" in navigator) {
    navigator.geolocation.getCurrentPosition(showPosition);
} else {
    console.log("地理定位不可用");
}

platform 操作系统

platform 属性是一个只读的字符串,声明了运行浏览器的操作系统和(或)硬件平台。

userAgent 用户代理

userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
一般来讲,它是在 navigator.appCodeName 的值之后加上斜线和 navigator.appVersion 的值构成的。
例如 “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36”

注 用户代理头中也有个 user-agent header


screen 屏幕信息

screen.width;       // 屏幕宽度(以像素为单位)
screen.height;      // 屏幕高度
screen.availWidth;  // 可用屏幕宽度(减去窗口装饰)
screen.availHeight; // 可用屏幕高度
screen.colorDepth;  // 颜色深度(位)
screen.pixelDepth;  // 像素深度(位)

// 应用场景:响应式设计
if (screen.width < 768) {
    document.body.classList.add("mobile-layout");
}

console 控制台

console 提供浏览器控制台接口

console.log("日志消息");
console.error("错误消息");
console.warn("警告消息");
console.info("信息消息");
console.debug("调试消息");

console.group("分组标题");
console.log("组内消息");
console.groupEnd();

console.table([{name: "John", age: 30}, {name: "Jane", age: 25}]);

// 计时功能
console.time("timer");
// 执行一些操作...
console.timeEnd("timer"); // 显示执行时间

history 历史记录

history.length;     // 历史记录中的条目数
history.state;      // 当前历史记录的关联状态对象

history.back();     // 返回上一页
history.forward();  // 前进到下一页
history.go(-2);     // 后退两页

// 添加历史记录并更改URL(不会实际加载页面)
history.pushState({page: "settings"}, "Settings", "/settings"); 

sessionStorage 会话存储

会话存储(标签页关闭时清除)
不同 源(Origin) 之间 sessionStorage 是隔离的,不同标签页之间也是隔离的。

sessionStorage.setItem("sessionId", "xyz123");
const id = sessionStorage.getItem("sessionId");

localStorage 持久化存储

持久性存储(关闭浏览器后仍然存在)
不同 源(Origin) 之间 localStorage 是隔离的。

// 保存数据
localStorage.setItem("username", "john_doe");
localStorage.setItem("preferences", JSON.stringify({theme: "dark"}));

// 读取数据
const username = localStorage.getItem("username");
const preferences = JSON.parse(localStorage.getItem("preferences"));

// 移除数据
localStorage.removeItem("username");
localStorage.clear(); // 清除所有

indexedDB 数据库

大型结构化数据存储
不同 源(Origin) 之间 indexedDB 是隔离的。

// 打开数据库
const request = indexedDB.open("myDatabase", 1);

request.onupgradeneeded = (event) => {
    const db = event.target.result;
    const store = db.createObjectStore("users", {keyPath: "id"});
    store.createIndex("email", "email", {unique: true});
};

request.onsuccess = (event) => {
    const db = event.target.result;
    
    // 添加数据
    const transaction = db.transaction("users", "readwrite");
    const store = transaction.objectStore("users");
    store.add({id: 1, name: "John", email: "john@example.com"});
    
    // 获取数据
    const getRequest = store.get(1);
    getRequest.onsuccess = () => {
        console.log(getRequest.result);
    };
};

DOM 操作

// 获取<html>元素,即 根元素
const root = document.documentElement;

// 获取<head>和<body>
const head = document.head;
const body = document.body;

// 获取所有<h1>元素
const headings = document.getElementsByTagName("h1");

// 使用CSS选择器查找元素
const element = document.querySelector("#container > .item");

// 遍历元素
const listItems = document.querySelectorAll("ul > li");
listItems.forEach(item => {
    console.log(item.textContent);
});

// 动态修改DOM
const newDiv = document.createElement("div");
newDiv.textContent = "新添加的元素";
document.body.appendChild(newDiv);

const toRemove = document.getElementById("oldElement");
toRemove.parentNode.removeChild(toRemove);

scrollTop()

scrollTop() 方法设置或返回被选元素的【垂直滚动条位置】,即元素距离他容器顶部的像素距离
当滚动条位置位于最顶部时,位置是0;即当一个元素的容器没有产生垂直方向的滚动条,那它的 scrollTop 的值默认为0。
当滚动条位置位于最底部时,位置是元素的高度;

1.未设置时默认为0
2.为负值时不做任何响应
3.设置为超出本身最大值时,默认为最大值

scrollTop() 实现聊天窗口自动滚动

<div id="div-received-msg" class="div-received-msg"></div>
// 始终显示滚动条最底部
$("#div-received-msg").scrollTop($("#div-received-msg").prop("scrollHeight"));

其中 scrollHeight 是对象的高度,包含内边距,但不包括水平滚动条、边框和外边距。

scrollTop() 实现瀑布数据流加载

如果元素滚动到底,下面等式返回true,没有则返回false.
element.scrollHeight - element.scrollTop === element.clientHeight


JavaScript 获取 html 元素值

JavaScript 中取得元素的方法有4种:分别是:

  • 1、getElementById() :通过id取得HTML元素。
  • 2、getElementsByName() :通过name取得元素,是一个数组。
  • 3、getElementsByTagName() :通过HTML标签取得元素,是一个数组。
  • 4、getElementsByClassName() :根据类名获得元素,是一个数组

getElementById()

getElementById() 方法可返回对拥有指定 ID 的第一个对象的引用。
HTML DOM 定义了多种查找元素的方法,除了 getElementById() 之外,还有 getElementsByName() 和 getElementsByTagName()。
不过,如果您需要查找文档中的一个特定的元素,最有效的方法是 getElementById()。
在操作文档的一个特定的元素时,最好给该元素一个 id 属性,为它指定一个(在文档中)唯一的名称,然后就可以用该 ID 查找想要的元素。

例1,获取元素标签内的值

<html>
  <head>
  <script type="text/javascript">
    function getValue()
      {
      var x=document.getElementById("myHeader")
      alert(x.innerHTML)
      }
  </script>
  </head>

  <body>
    <h1 id="myHeader" onclick="getValue()">This is a header</h1>
    <p>Click on the header to alert its value</p>
  </body>
</html>

例2,自定义id(x)方法
getElementById() 是一个重要的方法,在 DOM 程序设计中,它的使用非常常见。我们为您定义了一个工具函数,这样您就可以通过一个较短的名字来使用 getElementById() 方法了:

function id(x) {
  if (typeof x == "string") return document.getElementById(x);
  return x;
  }

上面这个函数接受元素 ID 作为它们的参数。对于每个这样的参数,您只要在使用前编写 x = id(x) 就可以了。


getElementsByName()

getElementsByName() 方法可返回带有指定名称的对象的集合。
该方法与 getElementById() 方法相似,但是它查询元素的 name 属性,而不是 id 属性。
另外,因为一个文档中的 name 属性可能不唯一(如 HTML 表单中的单选按钮通常具有相同的 name 属性),所有 getElementsByName() 方法返回的是元素的数组,而不是一个元素。

例,统计文档内name为myInput的标签有多少个

<html>
  <head>
    <script type="text/javascript">
    function getElements()
      {
      var x=document.getElementsByName("myInput");
      alert(x.length);
      }
    </script>
  </head>

  <body>
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <br />
    <input type="button" onclick="getElements()" value="名为 'myInput' 的元素有多少个?" />
  </body>
</html>

getElementsByTagName()

getElementsByTagName() 方法可返回带有指定标签名的对象的集合。
getElementsByTagName() 方法返回元素的顺序是它们在文档中的顺序。
如果把特殊字符串 “*” 传递给 getElementsByTagName() 方法,它将返回文档中所有元素的列表,元素排列的顺序就是它们在文档中的顺序。
注意:传递给 getElementsByTagName() 方法的字符串可以不区分大小写。

例1,统计文档内有多少个input标签

<html>
  <head>
    <script type="text/javascript">
      function getElements()
        {
        var x=document.getElementsByTagName("input");
        alert(x.length);
        }
    </script>
  </head>

  <body>
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <input name="myInput" type="text" size="20" /><br />
    <br />
    <input type="button" onclick="getElements()" value="How many input elements?" />
  </body>
</html>

例2,统计文档内有多少表格table

var tables = document.getElementsByTagName("table");
alert ("This document contains " + tables.length + " tables");

例3,获得文档中的第4个段落
如果您非常了解文档的结构,也可以使用 getElementsByTagName() 方法获取文档中的一个特定的元素。例如,下面的代码可以获得文档中的第四个段落:
var myParagragh = document.getElementsByTagName("p")[3];
不过,如果您需要操作某个特定的元素,使用 getElementById() 方法将更为有效。

例4,获取id=”main”的元素中的所有p元素
下面的例子返回包含文档中所有p元素的列表,并且这些p元素应该是 id=”main” 的元素的后代(子、孙等等):
document.getElementById("main").getElementsByTagName("p");


getElementsByClassName()

getElementsByClassName() 方法返回文档中所有指定类名的元素集合,作为 NodeList 对象,元素在集合中的顺序以其在代码中的出现次序排序。
若获取class为多个类的元素,多个类名使用空格分隔,如 “test demo”。
NodeList 对象代表一个有顺序的节点列表。NodeList 对象 我们可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。
提示: 你可以使用 NodeList 对象的 length 属性来确定指定类名的元素个数,并循环各个元素来获取你需要的那个元素。
注意: Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。

例1,获取class为”example”和”color”的所有元素
var x = document.getElementsByClassName("example color");

例2,统计文档中有多少个class为example的元素

<html>
  <body>
    <div class="example">样式 class="example" 的 div 元素</div>
    <div class="example">另外一个样式 class="example" 的 div 元素</div>
    <p class="example">样式 class="example" 的 p 元素</p>
    <p>点击按钮查看文档中有多少个类名为 "example" 的元素。</p>
    <button onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>
    <p id="demo"></p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example");
        document.getElementById("demo").innerHTML = x.length;
    }
    </script>
  </body>
</html>

例3,修改所有样式class为”example”的元素的背景颜色

<html>
  <head>
    <style>
      .example {
          border: 1px solid black;
          margin: 5px;
      }
    </style>
  </head>

  <body>
    <div class="example">样式 class="example" 的 Div 元素</div>
    <div class="example">另外一个样式 class="example" 的 Div 元素</div>
    <p class="example">样式为 class="example" 的 p 元素。</p>
    <p>这是一个插入在 p 元素中样式 class="example" 的<span class="example">span</span> 元素 。</p>
    <p>点击按钮修改所有样式 class="example" 的背景颜色。</p>
    <button class="example" onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example");
        var i;
        for (i = 0; i < x.length; i++) {
            x[i].style.backgroundColor = "red";
        }
    }
    </script>
  </body>
</html>

例4,修改第一个类为”example color”的div元素的背景颜色

<html>
  <head>
    <style>
      div {
          border: 1px solid black;
          margin: 5px;
      }
    </style>
  </head>

  <body>
    <div class="example">
      <p>P 元素在在第一个样式为 class="example" 的 Div 元素中。Div 的索引值为 0。</p>
    </div>
    <div class="example color">
      <p>P 元素在在第一个样式为 class="example color" 的 Div 元素中。Div 的索引值为 0。</p>
    </div>
    <div class="example color">
      <p>P 元素在在第二个样式为 class="example color" 的 Div 元素中。Div 的索引值为 1。</p>
    </div>
    <p>点击按钮修改第一个类为 "example color" 的 div 元素的背景颜色。</p>
    <button onclick="myFunction()">点我</button>
    <p><strong>注意:</strong> Internet Explorer 8 及更早 IE 版本不支持 getElementsByClassName() 方法。</p>

    <script>
    function myFunction() {
        var x = document.getElementsByClassName("example color");
        x[0].style.backgroundColor = "red";
    }
    </script>
  </body>
</html>

innerHTML 与 value 的区别

getElementById().innerHTML 与 getElementById().value 的区别
有value属性的标签才能操作其value值,只有input等表单输入标签才有value值。
例如:
<input type="text" id="txt1" value="hello"/>
这样一个元素,当你使用document.getElementById(“txt1”).value时,可以得到其value值,即”hello”这个字符串。
如果一个元素没有value值,那么使用document.getElementById().value时是取不到。这是理所当然的,没有的东西怎么访问?
比如一个div标记,就不一定有value值。

innerHTML是指元素起始标记和结束标记之间的内容。
例如:
<label id="lb1">this is a label</label>
当你使用document.getElementById(“lb1”).innerHTML可以取到<label></label>之间的内容,即“this is a label”。

一个实例如下:

<html>
  <head>
    <script type="text/javascript">
      function getValue()
      {
      var x=document.getElementById("myHeader")
      alert(x.innerHTML)
      }
      function getValue2()
      {
      var x=document.getElementById("myInput")
      alert(x.value)
      }
    </script>
  </head>

  <body>
    <h1 id="myHeader" onclick="getValue()">这是标题</h1>
    <input id="myInput" type="text" value="value值" onclick="getValue2()" />
    <p>点击标题,会提示出它的innerHTML值。</p>
    <p>点击input框,会提示出它的value值。</p>
  </body>
</html>

HttpOnly 的设计目的
​​安全机制​​:HttpOnly 是浏览器提供的安全特性
​​防 XSS​​:专门防御跨站脚本攻击 (XSS)
​​敏感数据保护​​:用于保护包含敏感信息(如会话 ID、身份令牌)的 Cookie

JavaScript 访问限制
document.cookie 属性会​​完全忽略​​所有标记为 HttpOnly 的 Cookie
JavaScript ​​无法通过任何 API​​ 读取 HttpOnly Cookie
即使尝试遍历 Cookie 或使用特殊技巧,仍然无法获取


对于同源请求,浏览器​​自动且无条件​​发送所有相关 Cookie,无需任何特殊 JS 设置(如 credentials: ‘include’)

例如
页面访问​​:http://localhost:8000/user/profile
​​API访问​​:http://localhost:8000/api/v1/user/findDetail
是同源的,所以会自动携带 access_token 等 Cookie
但是如果 api 接口是 http://api.localhost:8000/data 就不是同源了,不会自动携带 Cookie


document.cookie 返回结果样式 cookie1=value1; cookie2=value2; ...

// 设置cookie
document.cookie = "username=john_doe; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";

// 读取cookie
function getCookie(name) {
    const cookies = document.cookie.split(';');
    for (const cookie of cookies) {
        const [key, value] = cookie.split('=');
        if (key.trim() === name) return decodeURIComponent(value);
    }
    return null;
}

console.log(getCookie("username"));

https://github.com/js-cookie/js-cookie


优化

JavaScript 的性能优化:加载和执行
https://www.cnblogs.com/chutianshu1981/p/3792142.html

requestIdleCallback

requestIdleCallback 是浏览器 JavaScript 的一个 API,允许开发者在浏览器空闲时期调度低优先级的任务,避免阻塞关键操作(如用户交互、动画渲染),从而提升页面性能与用户体验。

用途:执行非紧急的后台任务(如日志上报、数据分析、预加载资源),不影响用户感知的延迟(如点击响应、动画流畅度)。

实现原理:

  • 浏览器在每一帧(通常 16ms/帧)中处理完高优先级任务后,若仍有空闲时间,则执行注册的 requestIdleCallback 回调。
  • 若无空闲时间,回调会延迟到下一次空闲时段执行。

用法:

const requestId = requestIdleCallback(callback[, options]);

参数​​:

  • callback:空闲时执行的函数,接收一个 IdleDeadline 对象作为参数。
  • options(可选):
    • timeout:指定回调超时时间(毫秒)。若超时后仍未空闲,浏览器会强制执行回调。

      ​返回值​​:唯一 ID(用于 cancelIdleCallback 取消回调)。

三方库

iziToast Toast通知

https://github.com/marcelodolza/iziToast

https://marcelodolza.github.io/iziToast/

<!-- 头部 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/css/iziToast.min.css">
<!-- 页面底部 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/js/iziToast.min.js"></script>

// 默认配置
iziToast.settings({
    position: 'topRight',           // 默认显示位置:右上角
    timeout: 3000,                  // 默认显示时间:3000毫秒(3秒)
    resetOnHover: true,             // 鼠标悬停时重置计时器
    transitionIn: 'fadeInLeft',     // 进入动画:从左淡入
    transitionOut: 'fadeOutRight',  // 退出动画:向右淡出
    closeOnClick: true,             // 点击关闭
    progressBar: true,              // 显示进度条
    layout: 1,                      // 布局样式:1表示纯色背景
    theme: 'light',                 // 主题:亮色
    maxWidth: 300                   // 最大宽度:300像素
});

// 几种预置通知类型
iziToast.info({...})    // 蓝色信息通知
iziToast.success({...}) // 绿色成功通知
iziToast.warning({...}) // 橙色警告通知
iziToast.error({...})   // 红色错误通知

// 自定义通知
iziToast.show({
  title: '提示',
  message: '这是来自 iziToast 的通知!',
  position: 'topCenter',
  timeout: 3000,
  progressBar: true,
  closeOnClick: true,
  backgroundColor: '#17a2b8',
  theme: 'dark'
});

常用参数:
title: 通知标题
message: 通知内容
position: 位置 (默认 bottomRight,支持 topRight, topCenter, bottomCenter 等)
timeout: 自动关闭时间(默认 5000 毫秒)
color: 通知背景色


FingerprintJS 浏览器指纹

https://github.com/fingerprintjs/fingerprintjs

https://fingerprintjs.github.io/fingerprintjs/

本地和服务器运行生成指纹不同问题

问题:
在同一台电脑的同一个 chrome 浏览器上访问包含 fingerprintjs 计算指纹的页面,通过 本地启动服务 localhost:8000 和 部署到 Linux 服务器后通过域名 http://devgou.com/ 访问,发现计算的设备指纹不同

排查及原因:
分别打开 localhost:8000 和 http://devgou.com/ 的浏览器控制台
把 fingerprintjs 指纹计算的结果在浏览器控制台输出

const fp = await FingerprintJS.load();
const result = await fp.get();

对比 components 中各个组件的属性,发现下面这些属性在两个环境中是不同的:

audio, canvas, colorGamut, contrast, deviceMemory, domBlockers, fontPreferences, fonts, screenFrame

解决:
不要使用默认的指纹生成方法,手动排除一些不稳定的动态组件,从而保持2个环境中生成的浏览器指纹相同。

代码如下:

// 稳定指纹检测函数
const getStableFingerprint = async () => {
  try {
    // 动态加载指纹库
    const script = document.createElement('script');
    script.src = 'https://openfpcdn.io/fingerprintjs/v4/iife.min.js';
    script.crossOrigin = 'anonymous';
    
    // 等待库加载完成
    await new Promise((resolve, reject) => {
      script.onload = resolve;
      script.onerror = reject;
      document.head.appendChild(script);
    });
    
    // 初始化指纹库
    const fp = await FingerprintJS.load();
    
    // 获取指纹结果
    const result = await fp.get();
    
    // 排除不稳定组件
    const {
      audio, canvas, colorGamut, contrast, deviceMemory,
      domBlockers, fontPreferences, fonts, screenFrame,
      ...stableComponents
    } = result.components;
    
    // 生成稳定指纹
    const stableVisitorId = FingerprintJS.hashComponents(stableComponents);
    
    // 返回结果
    return {
      originalVisitorId: result.visitorId,
      stableVisitorId,
      confidence: result.confidence,
      components: Object.keys(stableComponents)
    };
    
  } catch (error) {
    console.error('指纹检测失败:', error);
    return null;
  }
};

// 执行测试并显示结果
getStableFingerprint().then(result => {
  if (result) {
    console.log('✅ 稳定指纹:', result.stableVisitorId);
    console.log('🔒 原始指纹:', result.originalVisitorId);
    console.log('📊 使用的组件:', result.components.join(', '));
    console.log('⚖️ 置信度:', result.confidence.score);
  }
});

生成指纹时排除指定组件

排除指定组件的官方示例代码
https://github.com/fingerprintjs/fingerprintjs/blob/master/docs/extending.md

// ...

const result = await fp.get()

// The `languages` and `audio` components will be excluded
const { languages, audio, ...components } = result.components

// Optionally, you can make a visitor identifier from your custom list of components
const visitorId = FingerprintJS.hashComponents(components)

上一篇 Spring-JDBC

下一篇 c3p0

阅读
评论
11.4k
阅读预计49分钟
创建日期 2017-05-22
修改日期 2025-07-28
类别
目录
  1. Page Visibility API​​ 页面可见性API
    1. visibilityState 页面可见状态
    2. ​visibilitychange 页面可见状态变化事件
    3. 页面可见状态 visibilityState 与 窗口焦点状态 onfocus/onblur
    4. 实例:页面切换时暂停视频
  2. SharedWorker
    1. 创建 SharedWorker 实例
    2. self.onconnect
    3. MessagePort
    4. 查看 SharedWorker
    5. 通过 SharedWorker 在多页面间通信示例
  3. 变量
    1. 全局变量
    2. 局部变量
  4. use strict 严格模式
  5. 字符串
    1. 模板字符串
    2. 字符串判空
    3. 字符串等值比较
    4. 字符串大小比较
    5. substring()
    6. slice() 字符串切片
    7. startsWith() 以开头
    8. includes() 是否包含子串
    9. atob() base64 解码
  6. 数组
    1. forEach() 遍历
    2. map()
    3. reduce()
    4. js求集合并集交集差集
    5. js数组元素去重
    6. js数组判空
  7. 布尔值
  8. 对象
    1. 判断对象是否包含某个key
  9. 图片
    1. 图片file转base64
  10. Math 对象
    1. random() 0-1间的随机数
  11. Number 对象
    1. toString() 转化为字符串
  12. 全局函数
    1. encodeURIComponent()
    2. JSON.stringify() JSON序列化
    3. JSON.parse() JSON反序列化
  13. window 对象(浏览器窗口)
    1. window. 可省略
    2. document 对象
      1. referrer 上一个页面url
    3. location 对象
      1. href 页面完整url
      2. protocol 协议
      3. host 域名:端口号
      4. hostname 不带端口号的域名
      5. port 端口号
      6. pathname url的path
      7. search url的查询串
      8. hash 页内锚点
      9. origin 源信息(只读)
      10. 通过location获取当前页面的url等信息
      11. window.location与document.location
    4. navigator 浏览器及操作系统
      1. platform 操作系统
      2. userAgent 用户代理
    5. screen 屏幕信息
    6. console 控制台
    7. history 历史记录
    8. sessionStorage 会话存储
    9. localStorage 持久化存储
    10. indexedDB 数据库
  14. DOM 操作
    1. scrollTop()
      1. scrollTop() 实现聊天窗口自动滚动
      2. scrollTop() 实现瀑布数据流加载
    2. JavaScript 获取 html 元素值
      1. getElementById()
      2. getElementsByName()
      3. getElementsByTagName()
      4. getElementsByClassName()
      5. innerHTML 与 value 的区别
    3. cookie 操作
      1. JavaScript 无法读取 HttpOnly 的 Cookie
      2. 同源请求会自动携带 Cookie
      3. JavaScript 原生 Cookie 操作
      4. js-cookie 操作 cookie
  15. 优化
    1. requestIdleCallback
  16. 三方库
    1. iziToast Toast通知
    2. FingerprintJS 浏览器指纹
      1. 本地和服务器运行生成指纹不同问题
      2. 生成指纹时排除指定组件

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论