特性 | Cookie | Session | Token |
---|---|---|---|
存储位置 | 客户端 | 服务器端 | 客户端 |
安全性 | 较低(存储在客户端) | 较高(存储在服务器端) | 较高(签名验证) |
依赖 | 自动发送给服务器 | 依赖 Cookie 中的 session ID | 需手动添加到请求头中 |
生命周期 | 可设置过期时间 | 由服务器控制 | 由 Token 的过期时间决定 |
用途 | 用户偏好、会话标识 | 管理会话、存储临时数据 | API 认证、无状态身份验证 |
定义:一种使用现有技术(如 XMLHttpRequest
)实现异步请求的方法。
特点:
Promise
。示例代码:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
xhr.send();
定义:较新的 API,基于 Promise
,旨在替代 XMLHttpRequest
。
特点:
Promise
,支持 async/await
。示例代码:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
定义:一个基于 Promise
的第三方 HTTP 客户端库,适用于浏览器和 Node.js。
特点:
示例代码:
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
特性 | AJAX | Fetch | Axios |
---|---|---|---|
语法 | 回调函数 | 基于 Promise |
基于 Promise ,API 更简洁 |
错误处理 | 需手动检查状态码 | 不会自动抛出错误 | 自动抛出错误(非 2xx 状态) |
请求取消 | 不支持 | 需使用 AbortController |
提供取消请求的方法 |
浏览器支持 | 所有现代浏览器 | 不支持旧版浏览器(如 IE11) | 通过 polyfill 支持更广泛 |
功能丰富度 | 功能有限 | 功能较简单 | 提供拦截器、自动转换 JSON 等 |
document.getElementById()
:返回单个元素。document.getElementsByClassName()
:返回元素集合。document.querySelector()
:返回第一个匹配的元素。document.querySelectorAll()
:返回所有匹配的元素集合。document.createElement()
:创建新元素。appendChild()
或 insertBefore()
将新元素插入 DOM 树。element.setAttribute()
:设置属性。element.removeAttribute()
:移除属性。class
或 id
),可以直接通过点操作符设置,例如 element.className = 'new-class'
。element.innerHTML
:修改节点内的 HTML 内容。element.textContent
:修改节点内的纯文本内容。innerHTML
可以解析 HTML 标签,而 textContent
只处理纯文本。parentNode.appendChild()
:添加子元素。parentNode.removeChild()
:移除子元素。element.addEventListener()
:给元素绑定事件。element.cloneNode()
。element.parentNode
:获取父节点。element.childNodes
:获取子节点集合。element.firstChild
:获取第一个子节点。element.lastChild
:获取最后一个子节点。element.style
:操作内联样式。window.getComputedStyle()
:获取元素的计算样式。classList
属性:
element.classList.add('new-class')
:添加类名。element.classList.remove('new-class')
:移除类名。element.classList.toggle('new-class')
:切换类名。element.classList.contains('new-class')
:判断是否包含类名。"use strict"
是什么意思?使用它有什么区别?"use strict"
是 JavaScript 中的一个指令,用于启用严格模式(Strict Mode)。它必须放在脚本或函数的开头,指定代码在严格模式下运行。严格模式会限制一些不规范的语法,帮助开发者写出更安全、更规范的代码。
变量必须声明后才能使用
"use strict";
x = 3.14; // 错误:x 未声明
禁止使用 with
语句
"use strict";
with (Math) { x = cos(2); } // 语法错误
eval
作用域
eval()
中的代码会在自己的作用域中执行,而不是在当前作用域中。禁止 this
关键字指向全局对象
"use strict";
function f() {
return this;
}
f(); // 返回 `undefined`,而不是全局对象
函数参数不能重名
"use strict";
function sum(a, a, c) { // 语法错误
return a + a + c;
}
禁止八进制数字语法
"use strict";
var sum = 015 + 197 + 142; // 语法错误
禁止对只读属性赋值
"use strict";
var obj = {};
Object.defineProperty(obj, "x", { value: 0, writable: false });
obj.x = 3.14; // 抛出错误
禁止删除不可删除的属性
"use strict";
delete Object.prototype; // 抛出错误
使用 "use strict"
可以帮助开发者避免一些常见的错误,提高代码的安全性和可维护性。它还消除了代码运行的一些不安全之处,保证代码运行的安全,提高编译器效率,增加运行速度。
instanceof
运算符
prototype
属性是否出现在某个实例对象的原型链上。class Animal {}
class Dog extends Animal {}
const dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(dog instanceof Object); // true
constructor
属性
constructor
属性,指向创建该对象的构造函数。console.log(dog.constructor === Dog); // true
Object.prototype.isPrototypeOf()
方法
console.log(Dog.prototype.isPrototypeOf(dog)); // true
console.log(Animal.prototype.isPrototypeOf(dog)); // true
Object.getPrototypeOf()
方法
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
自定义类型检查函数
function isDog(obj) {
return obj && typeof obj === 'object' && obj.constructor === Dog;
}
console.log(isDog(dog)); // true
Symbol.hasInstance
instanceof
的行为。class MyClass {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([] instanceof MyClass); // true
instanceof
和 isPrototypeOf()
可以检查整个原型链,但可能会受到原型链被修改的影响。constructor
属性可以被重写,因此不总是可靠。Object.getPrototypeOf()
更可靠,但只检查直接原型。instanceof
是最常用的方法,因为它简单直观,并且能够处理继承关系。mouseover
和 mouseenter
事件的区别是什么?mouseover
会冒泡,mouseenter
不会。
mouseover
:鼠标指针进入元素或其子元素时触发。mouseenter
:仅在鼠标指针进入元素本身时触发,不会在进入子元素时触发。mouseover
:会冒泡,即鼠标从子元素移出到父元素时也会触发。mouseenter
:不会冒泡,仅在进入元素时触发。mouseover
。mouseenter
。const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('mouseover', () => {
console.log('Parent mouseover');
});
parent.addEventListener('mouseenter', () => {
console.log('Parent mouseenter');
});
child.addEventListener('mouseover', () => {
console.log('Child mouseover');
});
child.addEventListener('mouseenter', () => {
console.log('Child mouseenter');
});
mouseover
会在子元素和父元素上都触发。mouseenter
只会在最初进入父元素时触发一次。substring
和 substr
函数的区别是什么?参数含义
substring(start, end)
:返回从 start
到 end
(不包括 end
)之间的字符串。substr(start, length)
:返回从 start
开始的 length
个字符。let str = "Hello, World!";
console.log(str.substring(0, 5)); // "Hello"
console.log(str.substr(0, 5)); // "Hello"
负值参数的处理
substring
:将负值参数转换为 0。substr
:允许第一个参数为负值,从字符串末尾开始计数。console.log(str.substring(-3)); // "Hello, World!"
console.log(str.substr(-3)); // "ld!"
参数顺序
substring
:会自动调整参数顺序,使 startIndex
总是小于等于 endIndex
。substr
:不会调整参数顺序。console.log(str.substring(5, 2)); // "llo"
console.log(str.substr(5, 2)); // ", "
浏览器兼容性和未来发展
substring
:在所有现代浏览器中都得到了很好的支持。substr
:虽然目前仍被广泛支持,但已被 MDN 标记为废弃(deprecated),未来可能会被移除。可以使用更现代的 slice
方法来替代 substring
:
console.log(str.slice(0, 5)); // "Hello"
console.log(str.slice(-3)); // "ld!"
splice
和 slice
函数会改变原数组吗?splice()
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(2, 2); // 从索引 2 开始删除 2 个元素
console.log(arr); // [1, 2, 5]
console.log(removed); // [3, 4]
slice()
const arr = [1, 2, 3, 4, 5];
const sliced = arr.slice(1, 3); // 从索引 1 开始到索引 3 结束(不包括索引 3)
console.log(arr); // [1, 2, 3, 4, 5]
console.log(sliced); // [2, 3]
使用 pop()
方法
let fruits = ['apple', 'banana', 'orange'];
let lastFruit = fruits.pop();
console.log(lastFruit); // "orange"
console.log(fruits); // ['apple', 'banana']
使用 splice()
方法
let fruits = ['apple', 'banana', 'orange'];
let removedFruits = fruits.splice(-1, 1);
console.log(removedFruits); // ['orange']
console.log(fruits); // ['apple', 'banana']
使用 slice()
方法
let fruits = ['apple', 'banana', 'orange'];
let newFruits = fruits.slice(0, -1);
console.log(newFruits); // ['apple', 'banana']
console.log(fruits); // ['apple', 'banana', 'orange']
修改数组的 length
属性
let fruits = ['apple', 'banana', 'orange'];
fruits.length = fruits.length - 1;
console.log(fruits); // ['apple', 'banana']
pop()
或 splice()
。slice()
。length
属性也是一种简单高效的方法,但需注意代码的可读性。判断网页元素是否到达可视区域是一个常见的需求,尤其在实现懒加载、无限滚动或者触发动画等场景中非常有用。以下是几种常见的方法:
特点:
示例代码:
JavaScript
复制
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('元素进入可视区域');
// 在这里执行你的逻辑
}
});
});
const target = document.querySelector('#your-element');
observer.observe(target);
优点:
getBoundingClientRect()
方法特点:
示例代码:
JavaScript
复制
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// 使用
const element = document.querySelector('#your-element');
if (isElementInViewport(element)) {
console.log('元素在可视区域内');
}
优化建议:
示例代码(节流优化):
JavaScript
复制
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
window.addEventListener('scroll', throttle(() => {
if (isElementInViewport(element)) {
console.log('元素在可视区域内');
}
}, 100));
Element.checkVisibility()
方法特点:
示例代码:
JavaScript
复制
const element = document.querySelector('#your-element');
if (element.checkVisibility()) {
console.log('元素可见');
}
// 使用选项对象
element.checkVisibility({
checkOpacity: true, // 检查 opacity 是否为 0
checkVisibilityCSS: true // 检查 visibility CSS 属性
});
优点:
缺点:
Intersection Observer API
:
getBoundingClientRect()
方法:
Element.checkVisibility()
方法:
在实际开发中,优先选择 Intersection Observer API
,因为它既高效又易用。如果需要兼容旧版浏览器,可以使用 getBoundingClientRect()
方法,并结合节流或防抖技术优化性能。