ES6总结
1.let和const以及与var区别
1.1 作用域
var:
变量提升(Hoisting):var 声明的变量会被提升到其作用域的顶部,但赋值不会提升。这意味着你可以在声明之前引用该变量(但会得到 undefined)。
console.log(llb);var llb="123456789";
函数作用域:var 声明的变量在整个函数内都是可访问的,即使它们在代码块(如 if 语句或 for 循环)内声明。
let、const:
块级作用域:块是由 {} 包围的代码块。
没有变量提升:
//如果尝试在声明之前访问 let 变量,会抛出 ReferenceErrorconsole.log(xi);let xi='123456789';
常量:一旦 const 变量被赋值,其值就不能被重新赋值(但如果是对象或数组,其内容可以被修改)。
1.2 重复声明
var:
可以在同一作用域内多次声明同一个变量而不会报错。
let 和 const:
不允许在同一作用域内重复声明同一个变量,否则会抛出 SyntaxError。
1.3 重新赋值
var 和 let:
可以在声明后重新赋值。
const:
必须在声明时初始化,并且之后不能重新赋值(但如果是对象或数组,其内容仍然可以修改)
// let 示例
if (true) { let y = 20; console.log(y); // 输出: 20
}
// console.log(y); // 会抛出 ReferenceError,因为 let 有块级作用域 // const 示例
const z = { value: 30 };
console.log(z.value); // 输出: 30
z.value = 40;
console.log(z.value); // 输出: 40,对象内容可以修改
// z = {}; // 会抛出 TypeError,因为 const 不能重新赋值
2.解构赋值
一、数组解构赋值
数组解构允许直接从数组中提取值,将它们赋给声明的变量。使用方括号[]
包围变量名,并与待解构的数组相对应。
- 基本用法:
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3
- 忽略某些值:
如果解构的变量数量少于数组中的元素,未指定的元素将被忽略。
const [x, y] = [1, 2, 3, 4]; console.log(x); // 输出 1 console.log(y); // 输出 2
- 设置默认值:
以防解构的变量在数组中不存在,可以设置默认值。
const [x = 10, y = 20] = [1, 2];
console.log(x); // 输出 1
console.log(y); // 输出 2
注意,如果数组成员的值不严格等于undefined
,默认值不生效(null
的话相应值依然为null
)。
- 使用剩余参数:
使用剩余参数...rest
可以捕获数组中未指定的其余元素。
const [x, y, ...rest] = [1, 2, 3, 4, 5];
console.log(x); // 输出 1
console.log(y); // 输出 2
console.log(rest); // 输出 [3, 4, 5]
数组套数组的时候,可以使用同样的结构对应原数组,解构出对应的值。
let [a, [b, c, d]] = [1, [3, 4, 5]];
console.log(a, b, c, d); // 输出 1, 3, 4, 5
二、对象解构赋值
对象解构允许从对象中提取数据,并将它们赋值给声明的变量,这些变量名需要与对象的属性名相匹配(除非显式指定别名)。使用花括号{}
包围变量名和它们对应的属性名。
- 基本用法:
const obj = { name: 'Alice', age: 25 };
const { name, age } = obj;
console.log(name); // 输出 Alice
console.log(age); // 输出 25
- 设置别名:
可以为解构的属性设置别名。
const { name: userName, age: userAge } = obj;
console.log(userName); // 输出 Alice
console.log(userAge); // 输出 25
- 设置默认值:
对象解构赋值同样支持默认值。
const { address = 'Unknown' } = obj; console.log(address); // 输出 Unknown
注意,对象解构中的默认值生效条件是对象属性值严格等于undefined,null不会生效,解构失败值为undefined
- 剩余属性:
使用剩余参数...
可以捕获对象中未指定的其余属性。
const { address = 'Unknown', ...otherInfo } = obj;
console.log(address); // 输出 Unknown
console.log(otherInfo); // 输出 { age: 25 }
- 嵌套对象解构:
对象包含对象的时候,可以通过属性名:{}获取对应的属性值。
let person = { uname: 'zs', age: 34, dog: { name: '汪仔', age: 3 }, cat: { name: '小花', age: 2 } }; let { uname, cat: { name } } = person; console.log(uname, name); // 输出 zs, 小花
- 使用表达式:
解构赋值中,如果默认值是表达式,表达式惰性求值,只有在用到的时候才会去执行。默认值也可以引用解构赋值的其他变量,但该变量必须已声明。
三、解构赋值的应用场景
- 函数参数:
解构赋值可以用于函数参数,使函数更加简洁和易于理解。
function fn({ name, age }) {
console.log(name, age);
}
fn({ name: 'Alice', age: 25 }); // 输出 Alice, 25
- 遍历数据结构:
解构赋值可以用于遍历数组、对象、Map等数据结构。
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// 输出 first is hello, second is world
- 提取JSON数据:
在Ajax请求返回数据处理中,可以使用解构赋值提取JSON数据。
const data = { needServicePwd: true, needImgCode: false, needSmsCode: true };
({ needServicePwd: this.needServicePwd, needImgCode: this.needImgCode, needSmsCode: this.needSmsCode } = data);
3.模板字符串
一、定义与语法
ES6模板字符串:
使用反引号(`)包裹,而不是传统的单引号(')或双引号(")。
支持在字符串中嵌入表达式,通过${expression}的占位符语法实现。
ES5及之前字符串:
只能使用单引号或双引号包裹。
不支持在字符串中直接嵌入表达式,通常需要通过字符串拼接(使用+操作符)来实现。
二、功能特性
字符串插值:
ES6:支持字符串插值,允许在字符串中嵌入变量或表达式的结果。
let myname= 'John'; let greeting = `Hello ${myname}, how are you?`;console.log(greeting);
ES5及之前:不支持字符串插值,需要通过字符串拼接来实现。
let name = 'John'; let greeting = 'Hello, ' + name + '!';
多行字符串:
ES6:模板字符串默认支持多行,无需使用特殊的换行符或字符串连接符。
const name = "Alice";
const age = 30;
const personalInfo = `姓名: ${name}
年龄: ${age}
职业: 开发者`;
console.log(personalInfo);//输出:姓名: Alice 年龄: 30 职业: 开发者
ES5及之前:不支持多行字符串,需要使用字符串连接符(+)或数组(通过join方法)来创建多行字符串。
嵌套表达式:
ES6:允许在模板字符串的占位符中嵌套更复杂的表达式,包括函数调用、算术运算等。
let a1 = 5; let b1 = 10;let sum =`The sum of ${a1} and ${b1} is ${a1 + b1}`;
ES5及之前:不支持在字符串中直接嵌套表达式,需要通过字符串拼接和额外的计算来实现。
标签模板:
ES6:支持标签模板(tagged templates),允许在模板字符串前面加上一个标签函数来自定义字符串的处理方式
function greet(name) { return `你好, ${name}!`;
} const user = "Bob";
const message = `欢迎信息: ${greet(user)}
今天是个好日子。`; console.log(message);
ES5及之前:不支持标签模板,无法实现对字符串的自定义处理。
原始字符串:
ES6:通过String.raw方法可以创建原始字符串,即不进行特殊字符的转义处理。这对于处理包含转义字符的字符串特别有用。
let name = 'Alice';
console.log(String.raw`Hello, ${name}!`);
ES5及之前:无法直接创建原始字符串,需要手动处理转义字符。
4.ES6箭头函数
基本语法
箭头函数使用 => 符号来定义函数。以下是几种常见的用法:
没有参数或只有一个参数:
const sayHello = () => { console.log("Hello!");
}; //1)可以省略小括号,当形参只有一个的时候
const square = x => x * x;
多个参数:
const add = (a, b) => a + b;
带有函数体的箭头函数:
如果箭头函数需要包含多条语句,则必须使用花括号 {} 将它们包围起来,并且需要显式地返回结果(使用 return 关键字):
const multiplyAndAdd = (a, b, c) => { const result = a * b; return result + c;
};
特性
1.没有自己的 this:
箭头函数不会创建自己的 this 上下文,它会捕获其所在上下文的 this 值。这意味着在箭头函数内部使用 this,其值来自于箭头函数定义时的上下文,而不是调用时的上下文。
function Person() { this.age = 0; setInterval(() => { this.age++; // `this` 指向 Person 实例 console.log(this.age); }, 1000);
}
const p = new Person();
2.没有 arguments 对象:
箭头函数不提供 arguments 对象。如果需要访问函数的参数列表,可以使用剩余参数(...args)来替代:
const showArguments = (...args) => { console.log(args);
};
showArguments(1, 2, 3); // 输出: [1, 2, 3]
3.不能用作构造函数:
箭头函数不能使用 new 关键字来调用,因为它们没有 [[Construct]] 方法,不能被用作构造函数。
const Foo = () => {}; // 会抛出错误:TypeError: Foo is not a constructor
const bar = new Foo();
4.没有 prototype 属性:
由于箭头函数不能用作构造函数,因此它们也没有 prototype 属性。
const Foo = () => {};
console.log(Foo.prototype); // 输出: undefined
5.不支持 yield:
箭头函数不能用作生成器函数(即不能使用 yield 关键字)。
const gen = () => { yield 1; // 会抛出错误:SyntaxError: Unexpected strict mode reserved word
};
应用场景
以下是一个更复杂的示例,展示了箭头函数在数组操作中的应用:
const numbers = [1, 2, 3, 4, 5];
// 使用箭头函数计算数组元素的平方并返回一个新数组
const squares = numbers.map(x => x * x);
console.log(squares); // 输出: [1, 4, 9, 16, 25]
//找出大于2的数组const newArr2 = arr.filter(num => num >2);console.log(newArr2);
点击div改变颜色结合定时器(this指向外围作用域的this)
const box = document.getElementById('box');box.addEventListener('click', function(){setTimeout(() => {this.style.backgroundColor = 'blue';}, 2000);});
注意
- 箭头函数适合与this无关的问题的回调,定时器,数组的方法的回调
- 箭头函数不适合与this有关的回调,事件回调,对象的方法
5. ES6允许给函数的参数赋初始值
- 在 ES6(ECMAScript 2015)中,你可以在函数定义时为参数设置默认值。这使得函数调用时如果未提供某些参数,则会使用默认值。
- 带默认值的参数必须位于没有默认值的参数之后。如果违反这一规则,会导致语法错误。
//ES6允许给函数function的参数设置默认值,这样可以简化调用函数的过程const add=(a,b,c=10)=>{
return a + b + c;}console.log(add(1,2));console.log(add(1,2,3));
输出
函数赋值与解构赋值相结合
connect({name: 'Jack',age: 25,address: 'New York'
});function connect({name, age, address}){console.log(`My name is ${name}, I am ${age} years old, and I live in ${address}.`);
}
6. ES6扩展运算符(Spread Operator)和剩余参数(Rest Parameters)
ES6中的Rest参数(Rest parameters)是一种语法结构,它允许我们将一个不定数量的参数表示为一个数组
一、语法
Rest参数以三个点(...)开头,后跟一个参数名。这个参数名实际上是一个数组,用于收集函数调用时传入的所有剩余参数。
function myFunction(a, b, ...rest) { // rest是一个数组,包含所有剩余的参数 console.log(rest);
}
二、使用场景
处理可变数量的参数:
当函数需要接收任意数量的参数时,可以使用Rest参数来收集所有剩余的参数。
function sum(a, b, ...rest) { let total = a + b; for (let i = 0; i < rest.length; i++) { total += rest[i]; } return total;
} console.log(sum(1, 2, 3, 4, 5)); // 输出: 15
从数组中提取数据:
可以使用Rest参数将数组中的元素作为参数传递给函数。
const arr = [1, 2, 3, 4];
function printNumbers(...numbers) { numbers.forEach(num => console.log(num));
} printNumbers(...arr); // 输出: 1 2 3 4
结合其他参数使用:
Rest参数可以与其他参数一起使用,但必须放在参数列表的最后。
function processValues(operation, ...values) { if (operation === 'sum') { return values.reduce((acc, val) => acc + val, 0); } else if (operation === 'average') { const sum = values.reduce((acc, val) => acc + val, 0); return sum / values.length; } return null;
} console.log(processValues('sum', 1, 2, 3, 4)); // 输出: 10
console.log(processValues('average', 1, 2, 3, 4, 5)); // 输出: 3
三、注意事项
位置要求:
Rest参数必须放在参数列表的最后,且一个函数中只能有一个Rest参数。
参数解构:
Rest参数可以被解构,但需要注意解构后的变量名与数组元素的对应关系。
function f(...[a, b, c]) { return a + b + c;
} console.log(f(1, 2, 3)); // 输出: 6
console.log(f(1, 2, 3, 4)); // 输出: 6(第四值没有与之对应的变量名)
函数length属性:
函数的length属性返回的是没有Rest参数时的参数个数。
function example(a, b, ...c) {}
console.log(example.length); // 输出: 2
四、与扩展运算符的区别
虽然Rest参数和扩展运算符(Spread operator)都用到了三个点(...),但它们的作用和用途是不同的。Rest参数用于函数定义中,用于收集剩余的参数;而扩展运算符用于数组、对象等可迭代对象的展开。
// 扩展运算符示例
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // 将arr1的元素展开到arr2中 console.log(arr2); // 输出: [1, 2, 3, 4, 5]
数组中的扩展运算符
扩展运算符用三个点号(...
)表示,用于将数组元素展开到不同的地方。
示例1:合并数组
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const mergedArray = [...arr1, ...arr2];
console.log(mergedArray); // 输出: [1, 2, 3, 4, 5, 6]
示例2:在数组字面量中使用
const elements = ['fire', 'air'];
const nature = ['earth', ...elements, 'water'];
console.log(nature); // 输出: ['earth', 'fire', 'air', 'water']
示例3:将类数组对象转换为数组
const arrayLike = {0: 'a', 1: 'b', length: 2};
const arr = [...arrayLike];
console.log(arr); // 输出: ['a', 'b']
示例4:复制数组
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
console.log(copiedArray); // 输出: [1, 2, 3]
函数中的剩余参数
剩余参数用三个点号(...
)表示,用于将函数接收到的所有剩余参数收集到一个数组中。
示例1:基本用法
function sum(...numbers) { return numbers.reduce((total, num) => total + num, 0); } console.log(sum(1, 2, 3, 4)); // 输出: 10
示例2:结合普通参数使用
function multiply(factor, ...numbers) {
return numbers.map(num => num * factor);
}
console.log(multiply(2, 1, 2, 3, 4)); // 输出: [2, 4, 6, 8]
对象中的扩展运算符
在 ES2018 中,扩展运算符也被引入到了对象中,用于合并和克隆对象。
示例1:合并对象
const obj1 = {a: 1, b: 2};
const obj2 = {b: 3, c: 4};
const mergedObj = {...obj1, ...obj2};
console.log(mergedObj); // 输出: {a: 1, b: 3, c: 4}
示例2:克隆对象
const originalObj = {a: 1, b: 2};
const clonedObj = {...originalObj};
console.log(clonedObj); // 输出: {a: 1, b: 2}
示例3:结合数组和对象使用
const people = [
{name: 'Alice', age: 25},
{name: 'Bob', age: 30}
];
const peopleWithCities = people.map(person => ({...person, city: 'New York'}));
console.log(peopleWithCities);
// 输出: [{name: 'Alice', age: 25, city: 'New York'}, {name: 'Bob', age: 30, city: 'New York'}]
注意事项
- 数组和对象的浅拷贝:扩展运算符执行的是浅拷贝,即只复制了对象的第一层属性。对于嵌套的对象或数组,深层次的引用仍会保留。
- 函数参数中的默认值:剩余参数不能用于设置默认参数值。
7.Symbol()类型运用
Symbol 是 ES6(ECMAScript 2015)中引入的一种新的原始数据类型,表示独一无二的值。与字符串和数字不同,每次创建一个新的 Symbol 时,即使它的描述相同,它们也是不同的值。这使得 Symbol 类型非常适合用作对象的唯一属性键,以避免属性名冲突。
创建 Symbol
要创建一个新的 Symbol,你可以使用 Symbol() 函数,并传递一个可选的描述字符串(该描述仅用于调试目的,不会影响 Symbol 的唯一性):
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false
console.log(sym1.toString()); // "Symbol(description)"
console.log(sym2.toString()); // "Symbol(description)"
使用 Symbol 作为对象属性键
Symbol 可以用作对象的属性键,这样可以确保属性键的唯一性:
const sym = Symbol('uniqueKey');
const obj = { [sym]: 'This is a unique property'
}; console.log(obj[sym]); // "This is a unique property" // 使用 for...in 循环无法遍历 Symbol 类型的属性
for (let key in obj) { console.log(key); // 不会输出任何内容
} // 使用 Object.keys() 也不会列出 Symbol 类型的属性
console.log(Object.keys(obj)); // [] // 使用 Object.getOwnPropertySymbols() 可以获取 Symbol 类型的属性
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(uniqueKey)] // 使用 Object.getOwnPropertyNames() 也不会列出 Symbol 类型的属性
console.log(Object.getOwnPropertyNames(obj)); // []
全局 Symbol 注册表
Symbol 还提供了一个全局注册表,使用 Symbol.for() 方法。此方法会检查传入的字符串是否已经存在于全局 Symbol 注册表中,如果存在则返回该 Symbol,否则创建一个新的 Symbol 并注册到表中:
const symGlobal1 = Symbol.for('globalKey');
const symGlobal2 = Symbol.for('globalKey'); console.log(symGlobal1 === symGlobal2); // true
与直接调用 Symbol() 创建的 Symbol 不同,通过 Symbol.for() 创建的 Symbol 是全局唯一的,即使它们在不同的代码块或文件中创建。
内置 Symbol 属性
JavaScript 还定义了一些内置的 Symbol 属性,这些属性通常用于对象方法的钩子(traps),如:
- Symbol.iterator:定义对象的默认迭代行为。
- Symbol.toPrimitive:定义对象在转换为原始值时的行为。
- Symbol.toStringTag:定义对象在 Object.prototype.toString.call() 时的返回值。
例如,定义一个可迭代对象:
const iterable = { [Symbol.iterator]() { let i = 0; const data = [1, 2, 3]; return { next() { if (i < data.length) { return { value: data[i++], done: false }; } else { return { done: true }; } } }; }
}; for (let value of iterable) { console.log(value); // 1, 2, 3
}
8.ES6-迭代器
ES6 引入了迭代器(Iterator)的概念,它是一种统一遍历不同数据结构(如数组、对象、Map、Set 等)的方式。迭代器对象实现了迭代协议,该协议规定了 next() 方法,该方法会返回迭代结果的对象,该对象包含两个属性:value 和 done。value 表示当前遍历到的值,done 是一个布尔值,表示遍历是否结束。
以下是关于 ES6 迭代器的一些关键点和用法示例:
可迭代对象(Iterable)
首先,要明白什么是可迭代对象。一个对象如果实现了 @@iterator 方法(在对象上或通过其原型链),那么它就是可迭代的。@@iterator 方法应该返回一个迭代器对象。
默认迭代器
对于内置的可迭代对象(如数组、字符串、Map 和 Set),JavaScript 提供了默认的迭代器。
const arr = [1, 2, 3];
const iter = arr[Symbol.iterator](); console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: undefined, done: true }
自定义迭代器
你也可以为自定义对象实现迭代器。为此,你需要在对象上定义 @@iterator 方法,或者在其原型链上定义。
const myIterable = { data: [1, 2, 3], [Symbol.iterator]() { let index = 0; const data = this.data; return { next() { if (index < data.length) { return { value: data[index++], done: false }; } else { return { value: undefined, done: true }; } } }; }
}; for (const value of myIterable) { console.log(value); // 1, 2, 3
}
使用 for...of 循环
for...of 循环是遍历可迭代对象的一种简洁方式。
const str = 'hello';
for (const char of str) { console.log(char); // h, e, l, l, o
}
迭代器的高阶应用
迭代器可以用于创建更高级的数据处理功能,如生成器(Generator)、解构赋值(destructuring assignment with rest)、扩展运算符(spread operator)等。
生成器函数(Generator Function)
生成器函数是 JavaScript ES6 引入的一种特殊类型的函数,它允许你暂停和恢复函数的执行。生成器函数使用 function* 语法来定义,并且可以在函数体内使用 yield 关键字来暂停函数的执行并返回一个值。每次调用生成器函数的 .next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束。
function* numberGenerator() { yield 1; yield 2; yield 3;
} const gen = numberGenerator(); console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
生成器函数传参情况
//生成器函数
function* myGenerator(a,b,c) { yield a; yield b; yield c;yield a+b+c;
} const gen=myGenerator(4,5,6);
console.log(gen.next().value); // 4
console.log(gen.next().value); // 5
console.log(gen.next().value); // 6
console.log(gen.next().value); // 15
console.log(gen.next().done); // true
console.log(gen.next().value); // undefined
for (const value of myGenerator(1,2,3)) { console.log(value);
}
解构赋值与扩展运算符
解构赋值和扩展运算符都可以与迭代器一起使用,以简洁的方式处理可迭代对象。
const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [2, 3, 4] const arrCopy = [...arr]; // 使用扩展运算符复制数组
9.ES6-class关键字
ES6引入了类(class)的概念,使面向对象编程在JavaScript中变得更加直观和易于管理。以下是关于ES6类属性以及继承的一些基本介绍和示例。
类属性
在ES6中,你可以在类中定义属性(包括静态属性和实例属性)。虽然ES6本身并没有直接提供类的实例属性的简洁语法,但可以通过在构造函数中定义或者在类字段语法(从ES2022/ES13开始引入)中定义属性。
在构造函数中定义属性
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
} greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
} const person = new Person('Alice', 30);
person.greet(); // Hello, my name is Alice and I am 30 years old.
使用类字段语法定义属性(ES2022/ES13+)
class Person {
name;
age; constructor(name, age) {
this.name = name;
this.age = age;
} greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
} const person = new Person('Alice', 30);
person.greet(); // Hello, my name is Alice and I am 30 years old.
类字段语法还支持在声明时直接初始化属性:
class Person {
name = 'Unknown';
age = 0; greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
} const person = new Person();
person.greet(); // Hello, my name is Unknown and I am 0 years old.
静态属性(Static Properties)
静态属性属于类本身,而不是类的实例。它们使用 static
关键字定义。
class MathUtils {
static PI = 3.14159; static circleArea(radius) {
return MathUtils.PI * radius * radius;
}
} console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.circleArea(5)); // 78.53975
继承
在ES6中,你可以使用 extends
关键字实现类的继承。子类可以使用 super
关键字调用父类的构造函数和方法。
class Animal {
constructor(name) {
this.name = name;
} speak() {
console.log(`${this.name} makes a sound.`);
}
} class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类的构造函数
this.breed = breed;
} speak() {
super.speak(); // 调用父类的方法
console.log(`${this.name} barks.`);
}
} const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak();
// Buddy makes a sound.
// Buddy barks.
静态方法的继承
静态方法不能被实例调用,也不能被子类的实例重写(尽管它们可以在子类中重新定义)。
class Parent {
static greet() {
console.log('Hello from Parent');
}
} class Child extends Parent {
static greet() {
console.log('Hello from Child');
}
} Parent.greet(); // Hello from Parent
Child.greet(); // Hello from Child
在这个例子中,Child
类有自己的 greet
静态方法,调用 Child.greet()
会输出 "Hello from Child",而不是从 Parent
类继承的方法。
总结
- 类属性:可以在构造函数中定义,或者在类字段语法中直接声明和初始化。
- 静态属性:使用
static
关键字定义,属于类本身而不是实例。 - 继承:使用
extends
关键字实现,super
关键字用于调用父类的构造函数和方法。
相关文章:

ES6总结
1.let和const以及与var区别 1.1 作用域 var: 变量提升(Hoisting):var 声明的变量会被提升到其作用域的顶部,但赋值不会提升。这意味着你可以在声明之前引用该变量(但会得到 undefined)。 con…...

晶体匹配测试介绍
一、晶体参数介绍 晶体的电气规格相对比较简单,如下: 我们逐一看看每个参数, FL就是晶体的振动频率,这个晶体是24.576MHz的。 CL就是负载电容,决定了晶体频率是否准确,包括外接的实际电容、芯片的等效电容以及PCB走线的寄生电容等,核心参数。 Frequency Tolerance是…...

超声波清洗机靠谱吗?适合学生党入手的四款眼镜清洗机品牌推荐!
有没有学生党还不知道双十一买什么?其实可以去看看超声波清洗机,说实话它的实用性真的很高,对于日常用于清洗眼镜真的非常合适,不仅可以帮助大家节约时间而且还能把眼镜清洗的干净透亮,接下来我就来为大家带来四款好用…...

Java生成图片_基于Spring AI
Spring AI 优势 过去,使用Java编写AI应用时面临的主要困境是没有统一且标准的封装库,开发者需自行对接各个AI服务提供商的接口,导致代码复杂度高、迁移成本大。如今,Spring AI Alibaba的出现极大地缓解了这一问题,它提…...

程序传入单片机的过程,以Avrdude为例分析
在市场上有各式各样的单片机,例如Arduino,51单片机,STM等。通常,我们都用其对应的IDE软件进行单片机的编程。这些软件既负责将程序代码转写成二进制代码,即机器语言,也负责将该二进制代码导入单片机。与此同…...

用YOLO和LLM增强的OCR
虽然最近我花了很多时间在大型语言模型 (LLM) 上进行实验,但我对计算机视觉的热情始终未减。因此,当我有机会将两者融合在一起时,我迫不及待地想要立即开始。在 Goodreads 上扫描书籍封面并将其标记为已读一直感觉有点神奇,我很兴…...

开源的云平台有哪些?
开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力,同时允许社区参与开发和改进。以下是一些知名的开源云平台: 1. OpenStack 简介:OpenStack:一个广泛使用的开源云平台,它由多个组件组成,提…...

Spring Boot学习资源库:微服务架构的加速器
3 系统分析 3.1可行性分析 在进行可行性分析时,我们通常根据软件工程里方法,通过四个方面来进行分析,分别是技术、经济、操作和法律可行性。因此,在基于对目标系统的基本调查和研究后,对提出的基本方案进行可行性分析。…...

Pi4+wfb-ng+8812au
sudo apt update将如下文件拷入树莓派4 linux-6f921e98008589258f97243fb6658d09750f0a2f.tar.gz libsodium.zip rtl8812au.zip wfb-ng_Pi4_2.zip 安装libsodium unzip libsodium.zip cd libsodium ./configure make && make check sudo make install#安装8812AU驱动 …...

基于单片机的非接触智能测温系统设计
本设计主要由单片机STC8A8K64S4A12、OLED显示屏、非接触式测温模块MLX9061、无线通讯模块ESP8266以及声光报警模块等构成。系统通过非接触式测温模块MLX9061测量当前人员温度,温度通过OLED显示屏进行实时显示,当被测温度高于阈值,声光报警模块…...

第二十三篇:网络拥塞了,TCP/IP如何解决的?
一.显示拥塞通知 当发生网络拥塞时,发送主机应该减少数据包的发送量。作为IP上层协议,TCP虽然也能控制网络拥塞,不过它是通过数据包的实际损坏情况来判断是否发生拥塞。然而这种方法不能在数据包损坏之前减少数据包的发送量。 为了解决这个…...

登录注册静态网页实现(HTML,CSS)
实现效果图 实现效果 使用HTML编写页面结构,CSS美化界面,点击注册,跳转到注册界面,均为静态网页,是课上的一个小作业~ 使用正则表达式对输入进行验证,包括邮箱格式验证,用户名格式验证。 正则…...

基于FPGA的以太网设计(二)
一.以太网硬件架构概述 前文讲述了以太网的一些相关知识,本文将详细讲解以太网的硬件架构 以太网的电路架构一般由MAC、PHY、变压器、RJ45和传输介质组成,示意图如下所示: PHY:Physical Layer,即物理层。物理层定义了…...

OJ在线评测系统 后端微服务架构 注册中心 Nacos入门到启动
注册中心 服务架构中的注册中心是一个关键组件,用于管理和协助微服务之间的通信。注册中心的主要职责是服务的注册和发现,确保各个微服务能够相互找到并进行调用。 主要功能: 服务注册:微服务在启动时,将自身信息&am…...

升级到Ubuntu 24.04遇到的问题
升级过程中被别人关机重启到windows了,再启动到linux接着升级,还好能运行。但出现了些问题。 1.网络无法访问,发现是dns问题。最后在/etc/systemd/resov.conf文件中添加nameserver sudo nano /etc/systemd/resolv.conf cd /etc sudo ln -s …...

提示词格式化
利用jinja2,对提示词进行格式输出。以下是qwen2中tokenizer_config.json文件中的chat_template模块定义的提示词转换方式。 (1)查看qwen2的chat_template {"add_prefix_space": false,"added_tokens_decoder": {"…...

JAVA八股文1
1.Java 基础 1.1 语法基础 封装 利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内…...

yum仓库安装rabbitmq
yum仓库安装rabbitmq 1、配置yum仓库 vim /etc/yum.repos.d/rabbitmq.repo # In /etc/yum.repos.d/rabbitmq.repo## ## Zero dependency Erlang ##[rabbitmq_erlang] namerabbitmq_erlang baseurlhttps://packagecloud.io/rabbitmq/erlang/el/7/$basearch repo_gpgcheck1 gpg…...

go语言中的函数详解
1. 引言 函数是编程中不可或缺的组成部分,无论是在Go语言还是其他编程语言中,函数都扮演着重要的角色。函数能够将一系列的操作封装在一起,使得代码更加模块化、可重用和易于维护。 在本文中,我们将详细介绍Go语言中函数的概念和…...

ubuntu18.04运行OpenPCDet出现的问题
一、概述 在编译成功OpenPCDet的源代码之后,发现在运行demo时候,依旧出现了很多问题,在此对出现的问题进行总结记录。 二、问题分析 (一)ModuleNotFoundError:No module named av2 如图所示 这个问题比较简单&#x…...

【C++】——继承(下)
【C】——继承(下) 5 继承与友元6 继承与静态成员7 多继承7.1 继承模型7.2 菱形继承的问题7.3 虚继承7.4 多继承中的指针偏移问题 8 组合与继承 5 继承与友元 友元关系不能被继承。即一个函数是父类的友元函数,但不是子类的友元函数。也就是说…...

Pandas处理时间序列之光谱分析与聚类
import matplotlib.pylab as plt %matplotlib inline import numpy as np from numpy import fft import pandas as pd 一、光谱分析 • 将时间序列分解为许多正弦或余弦函数的总和 • 这些函数的系数应该具有不相关的值 • 对正弦函数进行回归 光谱分析应用场景 基于光谱的…...

【WebGIS】Cesium:GeoJSON加载
GeoJSON 是一种常用的地理空间数据格式,它用于表示简单的地理要素及其属性,并且被广泛应用于 Web 地图和 GIS 系统中。在 Cesium 中,GeoJSON 文件可以很方便地加载到三维场景中展示,并且可以添加样式和事件处理。本文将为你提供详…...

PageHelper实现分页查询
前端发送的请求参数 后端返回的对象类型 Controller类实现 /*** 员工分页查询* param employeePageQueryDTO* return*/GetMapping("/page")ApiOperation("员工分页查询")public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO)…...

边缘检测评估方法:FOM、RMSE、PSNR和SSIM对比实验和理论研究
图像分割与边缘检测是密切相关的计算机视觉任务。以下图1展示了一个海岸线分割模型的输出示例: 图1: 分割掩码到边缘图的转换过程(数据集:LICS) 模型将每个像素分类为陆地或海洋(分割掩码)。随后,海岸线被定义为分类发生变化的像素位置(边缘图)。边缘检测可以通过提取图像分割…...

MySql 多表查询
多表查询:指从多张表中查询数据。 笛卡儿积:笛卡儿积是指在数学中,两个集合(A集合 和 B集合)的所有组合情况。 连接查询 内连接:相当于查询A、B交集部分数据外连接 左外连接:查询左表所有数据…...

数学建模算法与应用 第11章 偏最小二乘回归及其方法
目录 11.1 偏最小二乘回归概述 11.2 Matlab 偏最小二乘回归命令 Matlab代码示例:偏最小二乘回归 11.3 案例分析:化学反应中的偏最小二乘回归 Matlab代码示例:光谱数据的PLS回归 习题 11 总结 偏最小二乘回归(Partial Least …...

【MATLAB代码】TDOA定位,4个基站、3个时间差、三维定位(可直接复制粘贴到MATLAB上运行)
文章目录 程序结构源代码运行结果代码结构输入输出解析该MATLAB代码实现了基于时间差定位(TDOA, Time Difference of Arrival)的方法,使用最小二乘法在三维空间中估计一个未知点的位置。该算法利用一个主锚点和三个副锚点的已知位置,通过计算信号传播时间差来推算出目标位置…...

uniapp引入ThorUI的方法
1、下载文件 2、复制相应的文件除了pages 3、往项目中复制即可 4、引入即可实现 5、添加easycome自动引入...

面试官:手写一个New
在JavaScript中,new操作符主要用于创建一个对象示例。通过new操作符,可以创建一个新的对象,并将这个对象的原型链只想一个构造函数的原型对象,然后执行构造函数中的代码初始化这个新对象。 常见的new的使用为 new Array() new Set…...