JavaScript数据类型和声明语法

// JavaScript 数据类型

// 1. 原始类型 (Primitive Types)

// 字符串 (String)
let str = "Hello, World!"; // 表示文本数据,使用单引号或双引号

// 数字 (Number)
let num = 42; // 包括整数和浮点数,IEEE 754 双精度格式

// 布尔值 (Boolean)
let isTrue = true; // 表示真或假 (true / false)

// 未定义 (Undefined)
let notDefined; // 未赋值的变量默认为 undefined

// 空值 (Null)
let empty = null; // 表示一个空对象引用

// 符号 (Symbol)
let uniqueKey = Symbol("key"); // 创建唯一的标识符,ES6 引入

// 大整数 (BigInt)
let bigNum = 1234567890123456789012345678901234567890n; // 表示超大整数,需加 "n" 后缀


// 2. 引用类型 (Reference Types)

// 对象 (Object)
let obj = { name: "Alice", age: 25 }; // 存储键值对的集合

// 数组 (Array)
let arr = [1, 2, 3, 4]; // 有序的数据集合,属于对象的子类型

// 函数 (Function)
function greet() {
return "Hello!";
} // 可调用的对象,用于执行代码

// 日期 (Date)
let date = new Date(); // 表示日期和时间的对象

// 正则表达式 (RegExp)
let pattern = /abc/i; // 表示正则表达式,用于模式匹配

// 错误 (Error)
let error = new Error("An error occurred"); // 表示错误对象

// 3. 特殊类型

// NaN (Not a Number) - 表示非数字结果
let invalidNumber = 0 / 0; // 运算产生非数字结果

// Infinity - 表示无穷大
let inf = 1 / 0; // 运算产生无穷大


// 变量声明方式

// 使用 var - 函数作用域,允许重复声明
var myVar = "Old variable"; // 不推荐使用,易导致作用域混乱

// 使用 let - 块级作用域,不允许重复声明
let myLet = "New variable"; // 常用来声明可变变量

// 使用 const - 块级作用域,不允许重复声明,且值不可变
const myConst = "Constant variable"; // 常用于声明常量

// JavaScript 中数据类型检查
console.log(typeof myLet); // 使用 typeof 运算符检查类型
console.log(Array.isArray(arr)); // 判断是否为数组


JavaScript里的构造函数理解

在JavaScript中,构造函数是普通函数的一种特殊用法,用于创建和初始化对象。在 JavaScript 中,通过函数来定义构造函数,并使用 `new`​ 关键字来创建实例。
  • 构造函数本质上是普通函数,但是调用时要使用 new​ 关键字。
  • this​ 关键字指向新创建的对象。
  • 构造函数没有返回值(即使你在构造函数内 return​ 了一个对象,也会返回该对象,覆盖默认行为)。
  • 如果构造函数没有显式定义 return​,它会默认返回 this​(即实例对象)。
function Person(name, age) {
this.name = name;
this.age = age;
}

// 使用 new 创建实例
const person1 = new Person('Alice', 30);
console.log(person1.name); // Alice
console.log(person1.age); // 30

ES6 类的构造函数

ES6 引入了类(`class`​)的概念,提供了一种更清晰、更现代的方式来定义构造函数和对象的创建。类本质上是语法糖,背后依然是基于构造函数。
  • 类中的构造函数是通过 constructor​ 关键字定义的。
  • 类的构造函数与普通的构造函数一样,用于实例化对象并初始化对象属性。
  • 类的构造函数也是由 new​ 关键字调用的。
  • 类的 constructor​ 方法只能有一个,如果没有定义,JavaScript 会自动提供一个默认的构造函数。
  • 与构造函数不同,类的语法更加面向对象,提供了更明确的继承和方法定义。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

// 使用 new 创建实例
const person1 = new Person('Alice', 30);
console.log(person1.name); // Alice
console.log(person1.age); // 30

尽管ES6的类和构造函数看起来有很多相似之处,实际上它们的内部机制还是存在差异的。例如,在类的背后,实际上是通过构造函数来创建实例的:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

const person1 = new Person('Alice', 30);

背后实际上是这样的构造函数(类似于 ES5 中的函数式构造器):

function Person(name, age) {
this.name = name;
this.age = age;
}

const person1 = new Person('Alice', 30);

JavaScript对象

image

每个对象有其自身的众多方法。

比如说对字符串进行分割等方法,就要从String对象里去找对应方法。

Html Dom操作

Html Dom 有七大对象

image

每个对象里有相关的方法。

// 常用 HTML DOM 方法总结

// 查找元素相关方法
document.getElementById("id"); // 根据元素 ID 获取元素
document.getElementsByClassName("class"); // 根据类名获取元素集合
document.getElementsByTagName("tag"); // 根据标签名获取元素集合
document.querySelector("selector"); // 根据 CSS 选择器获取第一个匹配的元素
document.querySelectorAll("selector"); // 根据 CSS 选择器获取所有匹配的元素集合

// 创建和插入元素
document.createElement("tag"); // 创建一个新元素
element.appendChild(newElement); // 将子元素插入到元素内部的末尾
element.insertBefore(newElement, reference); // 在参考元素之前插入新元素
element.insertAdjacentHTML(position, html); // 在指定位置插入 HTML 代码

// 修改元素内容和属性
element.innerHTML = "HTML content"; // 设置或获取元素的 HTML 内容
element.textContent = "Text content"; // 设置或获取元素的文本内容
element.setAttribute("attribute", "value"); // 设置元素的属性
element.getAttribute("attribute"); // 获取元素的属性值
element.removeAttribute("attribute"); // 移除元素的属性

// 删除元素
element.removeChild(childElement); // 删除指定的子元素
element.remove(); // 删除元素本身(现代方法)

// 事件处理
element.addEventListener("event", function); // 为元素添加事件监听器
element.removeEventListener("event", function); // 移除事件监听器
element.onclick = function() { /* code */ }; // 使用属性的方式添加点击事件

// 样式和类操作
element.style.property = "value"; // 设置内联样式
element.classList.add("class"); // 添加一个类
element.classList.remove("class"); // 移除一个类
element.classList.toggle("class"); // 切换类的存在状态
element.classList.contains("class"); // 检查类是否存在

// 尺寸和位置
element.offsetWidth; // 获取元素的宽度(包括内边距和边框)
element.offsetHeight; // 获取元素的高度(包括内边距和边框)
element.scrollTop; // 获取或设置元素的垂直滚动位置
element.scrollLeft; // 获取或设置元素的水平滚动位置

// 节点遍历
element.parentNode; // 获取父节点
element.childNodes; // 获取所有子节点(包括文本和注释节点)
element.firstChild; // 获取第一个子节点
element.lastChild; // 获取最后一个子节点
element.nextSibling; // 获取下一个兄弟节点
element.previousSibling; // 获取上一个兄弟节点
element.children; // 获取所有子元素(不包括文本和注释节点)

// 属性快捷操作
element.id; // 直接获取或设置元素的 id
element.className; // 直接获取或设置元素的类名
element.src; // 获取或设置元素的 src 属性(如 img 标签)

// 表单操作
document.forms["formName"]; // 获取表单
formElement.submit(); // 提交表单
formElement.reset(); // 重置表单
inputElement.value; // 获取或设置输入元素的值
inputElement.checked; // 获取或设置复选框或单选按钮是否被选中

// 常用方法

// 1. document.getElementById() - 根据 ID 获取元素
const elementById = document.getElementById('myId'); // 获取 ID 为 myId 的元素

// 2. document.querySelector() - 获取第一个符合选择器的元素
const firstElement = document.querySelector('.myClass'); // 获取第一个 class 为 myClass 的元素

// 3. document.querySelectorAll() - 获取所有符合选择器的元素(返回 NodeList)
const allElements = document.querySelectorAll('.myClass'); // 获取所有 class 为 myClass 的元素

// 4. document.getElementsByClassName() - 根据类名获取元素(返回 HTMLCollection)
const elementsByClassName = document.getElementsByClassName('myClass'); // 获取 class 为 myClass 的元素集合

// 5. document.getElementsByTagName() - 根据标签名获取元素(返回 HTMLCollection)
const elementsByTagName = document.getElementsByTagName('div'); // 获取所有 div 标签的元素集合

// 6. element.textContent - 获取或设置元素的文本内容
elementById.textContent = 'Hello, World!'; // 设置文本内容为 'Hello, World!'

// 7. element.innerHTML - 获取或设置元素的 HTML 内容
elementById.innerHTML = '<span>Hi!</span>'; // 设置 HTML 内容为 <span>Hi!</span>

// 8. element.setAttribute() - 设置元素的属性
elementById.setAttribute('data-value', '123'); // 设置 data-value 属性为 '123'

// 9. element.getAttribute() - 获取元素的属性
const attrValue = elementById.getAttribute('data-value'); // 获取 data-value 属性的值

// 10. element.removeAttribute() - 移除元素的属性
elementById.removeAttribute('data-value'); // 移除 data-value 属性

// 11. element.appendChild() - 将一个子元素添加到当前元素
const newElement = document.createElement('p');
elementById.appendChild(newElement); // 将新元素 p 添加为 ID 为 myId 的元素的子元素

// 12. element.removeChild() - 移除一个子元素
elementById.removeChild(newElement); // 移除 ID 为 myId 的元素的子元素 newElement

// 13. element.replaceChild() - 替换一个子元素
const anotherElement = document.createElement('div');
elementById.replaceChild(anotherElement, newElement); // 用 anotherElement 替换 newElement

// 14. element.classList.add() - 为元素添加一个 class
elementById.classList.add('newClass'); // 添加 class 'newClass'

// 15. element.classList.remove() - 移除元素的一个 class
elementById.classList.remove('newClass'); // 移除 class 'newClass'

// 16. element.classList.toggle() - 切换元素的 class
elementById.classList.toggle('newClass'); // 如果存在则移除,否则添加 class 'newClass'

// 17. element.style.property - 设置元素的样式
elementById.style.color = 'red'; // 设置元素的文本颜色为红色


// 其他方法

// 1. document.createElement() - 创建一个新的元素
const newDiv = document.createElement('div'); // 创建一个新的 div 元素

// 2. document.createTextNode() - 创建一个文本节点
const textNode = document.createTextNode('Hello!'); // 创建一个内容为 'Hello!' 的文本节点

// 3. element.insertAdjacentHTML() - 在指定位置插入 HTML
elementById.insertAdjacentHTML('beforeend', '<p>Inserted text</p>'); // 在元素内部结束标签前插入 HTML

// 4. element.closest() - 查找匹配选择器的最近父元素
const closestDiv = elementById.closest('div'); // 获取 ID 为 myId 的元素最近的 div 父元素

// 5. element.parentNode - 获取元素的父元素
const parentElement = elementById.parentNode; // 获取 ID 为 myId 的元素的父元素

// 6. element.nextElementSibling - 获取元素的下一个兄弟元素
const nextSibling = elementById.nextElementSibling; // 获取 ID 为 myId 的元素的下一个兄弟元素

// 7. element.previousElementSibling - 获取元素的上一个兄弟元素
const prevSibling = elementById.previousElementSibling; // 获取 ID 为 myId 的元素的上一个兄弟元素

// 8. element.children - 获取元素的所有子元素(返回 HTMLCollection)
const childrenElements = elementById.children; // 获取 ID 为 myId 的元素的所有子元素

// 9. element.hasChildNodes() - 判断元素是否有子节点
const hasChildren = elementById.hasChildNodes(); // 如果 ID 为 myId 的元素有子节点则返回 true

// 10. element.cloneNode() - 克隆元素(参数为 true 时克隆所有子元素)
const clonedElement = elementById.cloneNode(true); // 克隆 ID 为 myId 的元素及其所有子节点

// 11. element.scrollIntoView() - 滚动元素到视口中
elementById.scrollIntoView({ behavior: 'smooth' }); // 平滑滚动到视口中

// 12. document.body.append() - 将元素添加到 body 中(可以是多个元素)
document.body.append(newDiv, anotherElement); // 将 newDiv 和 anotherElement 添加到 body 中

javascript原型和原型链

原型:

JavaScript中,**原型**是一个对象,它包含其他对象共有的属性和方法。每一个JavaScript对象都有一个隐式的内部属性`[[Prototype]]`​,这个属性指向该对象的原型对象。原型是对象的“模板”,包含共享的功能。

image

创建对象与原型

当你通过构造函数创建对象时,该对象会自动继承构造函数的原型。

function Person(name) {
this.name = name;
}

const person1 = new Person('John');
console.log(person1.__proto__ === Person.prototype); // true

上面的代码中,Person.prototype​是person1​对象的原型,person1​继承了Person​构造函数的原型。

修改原型

你可以在 构造函数的原型​ 上添加方法和属性,这些方法和属性会被所有通过该 构造函数创建的实例​ 共享。

Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};

person1.greet(); // 输出: Hello, my name is John

这样,greet​方法就可以被所有Person​实例共享。

原型链(Prototype Chain)

image

**原型链**是JavaScript用来实现继承的一种机制。每当访问对象的属性或方法时,JavaScript会首先查找对象本身是否存在该属性。如果找不到,就会沿着原型链向上查找,直到找到该属性或到达原型链的末端。

每个对象都有一个指向原型的隐式属性`[[Prototype]]`​。构造函数的`prototype`​对象作为实例对象的原型。当访问实例对象的属性时,JavaScript会按照以下步骤进行查找:
  1. 查找实例对象:首先查看实例对象本身是否包含该属性或方法。
  2. 查找原型对象:如果实例对象没有该属性,会查看其原型对象[[Prototype]]​。
  3. 查找原型链:如果原型对象没有该属性,继续查找该原型对象的原型,依此类推,直到Object.prototype​。

原型链的示例

const animal = {
sound: 'Roar'
};

function Tiger() {
this.type = 'Tiger';
}

Tiger.prototype = animal;

const tiger1 = new Tiger();
console.log(tiger1.sound); // 输出: Roar

在这个例子中,`tiger1`​没有`sound`​属性,但是通过原型链,JavaScript会查找`Tiger.prototype`​,发现它指向`animal`​对象,因此`sound`​属性通过原型链继承过来。

原型链的终点

原型链的终点是Object.prototype​。如果在原型链的任何位置都找不到目标属性,则返回undefined​。

const obj = {};
console.log(obj.toString()); // 这里的toString是从Object.prototype继承来的

原型和构造函数

每一个构造函数都有一个`prototype`​属性,它指向该构造函数的原型对象。构造函数本身也是一个对象,并且有一个`constructor`​属性,指向创建该构造函数的函数。
function Animal() {}
const animal = new Animal();

console.log(animal.constructor === Animal); // true

__proto__​ 与 prototype​ 区别

  • __proto__​ 是每个实例对象的内部属性,它指向该实例对象的原型。
  • prototype​ 是构造函数的一个属性,指向该构造函数的原型对象。

image

__proto__​用于访问对象的原型链,而prototype​用于访问构造函数的原型对象。

Object.create()​ 和原型链

Object.create()​可以用来创建一个具有指定原型的新对象。它返回的对象会自动继承传入对象的属性和方法。

const animal = {
sound: 'Roar'
};

const tiger = Object.create(animal);
console.log(tiger.sound); // Roar

在这个例子中,tiger​对象继承了animal​对象的sound​属性。

原型链的继承

JavaScript通过原型链实现继承,可以通过修改构造函数的原型来让对象继承其他对象的属性和方法。

function Animal() {
this.sound = 'Roar';
}

function Tiger() {
Animal.call(this); // 调用Animal构造函数
}

Tiger.prototype = Object.create(Animal.prototype); // 设置原型链继承
Tiger.prototype.constructor = Tiger;

const tiger1 = new Tiger();
console.log(tiger1.sound); // Roar

在这个例子中,`Tiger`​继承了`Animal`​的属性,通过`Object.create(Animal.prototype)`​让`Tiger`​的原型链指向`Animal`​的原型。

总结

  • 原型是对象的模板,所有对象通过原型来共享方法和属性。
  • 原型链是一个对象链表,用于实现继承。每个对象都有一个[[Prototype]]​指向其原型,访问属性时会沿着原型链向上查找。
  • 原型链的终点Object.prototype​,如果没有找到指定的属性,则返回undefined​。
  • prototype​是构造函数的属性,__proto__​是每个对象的属性,它们分别代表了构造函数的原型和对象的原型。

这些是JavaScript中的原型和原型链的基础知识,理解这些对于掌握JavaScript的继承、对象和面向对象编程非常重要。

正则表达式

https://www.runoob.com/java/java-regular-expressions.html

Xpath表达式

https://www.runoob.com/xpath/xpath-syntax.html