ES6新特性详解
文章目录
- 1. let和const
- 1.1 let声明变量
- 1.2 const声明常量
- 2. 模板字符串
- 3. 解构赋值
- 3.1 数组的解构赋值
- 3.2 对象的解构赋值
- 4. 函数扩展
- 4.1 参数默认值
- 4.2 剩余参数
- 4.3 箭头函数
- 5. 对象扩展
- 5.1 对象简写
- 5.2 属性名表达式
- 5.3 扩展运算符
- 6. Symbol
- 7. Iterator和Generator
- 7.1 Iterator
- 7.2 Generator
- 8. Proxy和Reflect
- 8.1 Proxy
- 8.2 Reflect
- 9. Promise
- 10. Async和Await
- 10.1 Async
- 10.2 Await
- 11. 类
- 11.1 类的定义和使用
- 11.2 类的继承
- 12. 模块
- 12.1 export
- 12.2 import
1. let和const
1.1 let声明变量
var
和 let
关键字的区别:
关键字 | 是否能重复声明变量 | 是否有块作用域 | 是否有变量提升 | 是否影响顶层对象 |
---|---|---|---|---|
var | √ | × | √ | √ |
let | × | √ | × | × |
1.let 不允许重复声明变量
// var允许重复声明变量
var a = 10;
var a = 10;
// let不允许重复声明变量
let a = 10;
let a = 10; // Uncaught SyntaxError: Identifier 'a' has already been declared
2.let 声明的变量有块作用域
// var声明的变量,没有块作用域
if (true) {var a = 10;console.log(a); // 10
}console.log(a); // 10
// let声明的变量,有块作用域
if (true) {let a = 10; console.log(a); // 10
}console.log(a); // Uncaught ReferenceError: a is not defined
3.let 声明的变量,没有变量提升
/* 由于有变量提升,以下代码会转换成如下:
var a;
console.log(a);
a = 10; */// var声明的变量,有变量提升
console.log(a); // undefined
var a = 10;
// let声明的变量,没有变量提升
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 10;
4.let 声明的变量,不会与顶层对象挂钩
顶层对象:在broswer环境中,指window对象;在node环境中指global对象
// var声明的变量,会与顶层对象挂钩
var a = 10;
console.log(window.a); // 10
// let声明的变量,不会与顶层对象挂钩
let a = 10;
console.log(window.a); // undefined
1.2 const声明常量
const 拥有 let 的全部特性,与 let 不同的是,const声明的变量是常量,一经声明,无法修改。
1.const声明的变量无法修改
// let声明的变量,可以修改
let a = 10;
a = 20;
// const声明的变量,无法修改
const a = 10;
a = 20; // Uncaught TypeError: Assignment to constant variable
2.const声明的变量必须声明时就初始化
const a; // Uncaught SyntaxError: Missing initializer in const declaration
3.当变量是对象时,虽然不能修改对象名,但是可以修改对象的内部属性
解释:因为对象是引用类型,对象名存的是一个地址,而改变对象的内部属性,并没有改变地址本身。
const obj = {name: "Bill",age: 18
};obj.age = 28;
console.log(obj); // {name: 'Bill', age: 28}
let
和const
的使用场景:默认情况下使用const
,在知道变量值需要修改时使用let
2. 模板字符串
模板字符串:其实就是占位符,这样就可以简化字符串拼接。
1.用于字符串拼接
const name = "Bill";
const age = 18;
const person = `my name is ${name}, my age is ${age}`;
console.log(person); // my name is Bill, my age is 18
2.支持使用表达式
// 1.支持四则运算
const a = 10;
const b = 20;
const result = `result is ${a + b}`;
console.log(result); // result is 30// 2.支持三元表达式
const isEqual = `结果是${a === 10 ? "相等" : "不相等"}`;
console.log(isEqual); // 结果是相等
3. 解构赋值
解构赋值:用于赋值运算,可以简化赋值。
3.1 数组的解构赋值
1.简化数组的赋值
const arr = [1, 2, 3];const [a, b, c] = arr; // 等价于 a=1, b=2, c=3
console.log(a, b, c); // 1 2 3const [d, , e] = arr; // 等价于 d=1, e=3
console.log(d, e); // 1 3
2.嵌套情况下的数组赋值
const arr = [1, [2, 3, 4], 5];
const [a, [b, c], d] = arr; // 等价于 a=1, b=2, c=3, d=5
console.log(a, b, c, d); // 1 2 3 5
3.2 对象的解构赋值
1.简化对象的赋值
const obj = {name: "Bill",age: 18
};const { name, age } = obj; // 等价于 name=obj.name, age=obj.age
console.log(name, age); // Bill 18
2.声明的变量名需要与对象的属性名一致时,否则在对象的属性名中匹配不到,得到的值是undefined
对象的解构赋值,变量赋值时会与属性名匹配,不会按照声明变量的前后顺序匹配
const obj = {name: "Bill",age: 18,addr: "Shanghai"
};const { name, addr, a } = obj; // 等价于 name=obj.name, addr=obj.addr
console.log(name, addr, a); // Bill Shanghai undefined
3.嵌套情况下的对象赋值
const obj = {name: "Bill",age: 18,other: {addr: "Shanghai",email: "xxx@163.com"}
};const {name,age,other: { email }
} = obj; // 等价于 name=obj.name, age=obj.age, email = obj.other.email
console.log(name, age, email); // Bill 18 xxx@163.com
4. 函数扩展
4.1 参数默认值
参数默认值:不传参时,函数使用默认的参数值,传参后会覆盖默认值。
function fn(a, b = 10) {console.log(a, b);
}fn(10); // 10 10
fn(10, 20); // 10 20
4.2 剩余参数
剩余参数:也称可变参数,剩余参数语法允许将一个不定数量的参数表示为一个数组。
function fn(a, b, ...args) {console.log(args);
}fn(10, 20, 30, 40, 50); // [30, 40, 50]
4.3 箭头函数
箭头函数:箭头函数可用于简化匿名函数的定义,使书写更为简洁。
1.无参数、无返回值的箭头函数
// 匿名函数写法,无参数、无返回值
const fn = function () {console.log(100);
};fn();
// 箭头函数写法,无参数、无返回值
const fn = () => {console.log(100);
};fn();
2.有返回值的箭头函数
// 匿名函数写法,有返回值
const fn = function () {console.log(100);return 100;
};
// 箭头函数写法,有返回值// 1.函数内部只有 return,无其它内容
const fn1 = () => 100;
const fn2 = () => ({ name: "Bill", age: 18 }); // 返回的是对象时,要使用小括号包裹起来// 2.函数内部除了有 return,还有其它内容
const fn3 = () => {console.log(100);return 100;
};
3.带参数的箭头函数
// 匿名函数写法,带参数
const fn = function (a, b) {console.log(a + b);return a + b;
};
// 箭头函数写法,带参数// 1.只有一个参数时,可以省略括号
const fn1 = a => {console.log(a);
};const fn2 = a => a;// 2.带多个参数时,不可省略括号
const fn3 = (a, b) => a + b;const fn4 = (a, b) => {console.log(a + b);return a + b;
};
4.箭头函数没有this
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><button value="按钮">点击按钮</button><script>const btn = document.querySelector("button");btn.addEventListener("click", function () {console.log(this.value); // 按钮// 使用匿名函数const fn = function () {console.log(this.value); // undefined};fn();});</script></body>
</html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><button value="按钮">点击按钮</button><script>const btn = document.querySelector("button");btn.addEventListener("click", function () {console.log(this.value); // 按钮// 使用箭头函数const fn = () => {console.log(this.value); // 按钮};fn();});</script></body>
</html>
注:监听事件的函数,要写成匿名函数,不要写成箭头函数,否则this指向的就是window
5. 对象扩展
5.1 对象简写
对象简写:简写对象的属性和方法
- 当属性名和属性值相同时,可以简写为只写一个属性名
- 可以省略方法中的
:function
// es5写法
const name = "Bill";
const obj = {name: name,test: function () {}
};
// es6写法
const name = "Bill";
const obj = {name,test() {}
};
5.2 属性名表达式
属性名表达式:对象的属性名,可以使用变量和表达式的方式命名
const name = "a";
const obj = {[name]: "Bill",[name + "bc"]: "Jackson"
};console.log(obj); // {a: 'Bill', abc: 'Jackson'}
注:对象简写和属性名表达式不能同时使用
5.3 扩展运算符
扩展运算符:用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
- 对象的扩展运算符:用于拷贝对象属性
- 数组的扩展运算符:将数组分割为参数序列、拷贝数组
1.拷贝对象
const obj1 = { name: "Bill", age: 18 };
const obj2 = { name: "Jackson" };
const obj3 = { addr: "Shanghai" };
const obj = { ...obj1, ...obj2, ...obj3 };
console.log(obj); // {name: 'Jackson', age: 18, addr: 'Shanghai'}
注:当对象有同名属性时,后合并的对象,会覆盖之前的对象的属性
2.拷贝数组
const arr1 = [10, 20, 30];
const arr2 = [10, 40, ...arr1];
console.log(arr2); // [10, 40, 10, 20, 30]
3.将数组分割为参数序列
const arr = [10, 30, 50];
console.log(Math.max(10, 20, ...arr)); // 50
剩余参数的
...
和扩展运算符...
的区别:
- 剩余运算符:把多个参数合并为一个数组
- 扩展运算符:把一个数组分割为多个参数
6. Symbol
Symbol:是一种基本数据类型,表示独一无二的值。
1.创建Symbol变量
// 1.创建不带描述的Symbol变量
const s1 = Symbol();
console.log(s1); // Symbol()// 2.带描述的Symbol变量
const s2 = Symbol("Symbol2"); // 传入的字符串为Symbol变量的描述
console.log(s2); // Symbol(Symbol2)
注:Symbol是基本数据类型,不是对象类型,所以不能使用new创建Symbol变量
2.Symbol的值是唯一的
const s1 = Symbol();
const s2 = Symbol();
console.log(s1 === s2); // falseconst s3 = Symbol("Symbol");
const s4 = Symbol("Symbol");
console.log(s3 === s4); // false
3.Symbol变量不能进行运算
const s = Symbol();
console.log(s + "hello"); // Uncaught TypeError: Cannot convert a Symbol value to a string
7. Iterator和Generator
7.1 Iterator
迭代:从一个数据集合中按照一定的顺序,不断取出数据的过程。
迭代器(Iterator):
- 为各种数据结构,提供了一个可以统一、简便的访问接口
- 使得数据结构的成员,能够按照某种顺序排列
Symbol.iterator
为对象定义了迭代器,可以被for...of
循环使用
1.当对象具有Symbol.iterator
接口时,就可以使用for...of
迭代对象
1.原生具备
Symbol.iterator
接口的数据结构有:Array、Set、Map、String、arguments、NodeList
2.for...of
是语法糖,本质上还是用的迭代器方法
const arr = [1, 3, 5, 7, 9];
console.log(arr);for (const i of arr) {console.log(i);
}
点击Array对象,展开[[Prototype]]: Array(0)
以后,发现具有Symbol(Symbol.iterator) : ƒ values()
,因此可以使用for...of
遍历数组。
2.通过 Symbol.iterator
来创建迭代器
const arr = [1, 3, 5, 7, 9];
const iter = arr[Symbol.iterator](); // 创建迭代器console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: 7, done: false}
console.log(iter.next()); // {value: 9, done: false}
console.log(iter.next()); // {value: undefined, done: true}
next方法返回一个对象,该对象包含两个属性:
- value:下一个数据的值
- done:已经迭代到序列中的最后一个值,为 true,否则为false
Iterator 的遍历过程:
- 创建一个指针对象,指向当前数据结构的起始位置。也就是说,迭代器对象本质就是一个指针对象。
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
- 第二次调用指针对象的next方法,可以将指针指向数据结构的第二个成员。
- 不断地调用指针对象的next方法,直到它指向数据结构的结束位置。
7.2 Generator
Generator(生成器)函数:
- 是一种异步编程解决方案
- 是一个状态机,封装了多个内部状态
- 执行Generator函数会返回一个遍历器对象,可以遍历每一个状态
1.next
方法执行下一个状态,一个yield
代表一个状态,碰到yield
停下
function* gen() {console.log(10);yield;console.log(20);yield;console.log(30);
}const g = gen();
g.next(); // 10
g.next(); // 20
g.next(); // 30
2.yield
可以跟返回的结果
function* gen() {console.log(10);yield "aaa";console.log(20);yield "bbb";console.log(30);return "ccc";
}const g = gen();
const res1 = g.next(); // 10
console.log(res1); // {value: 'aaa', done: false}const res2 = g.next(); // 20
console.log(res2); // {value: 'bbb', done: false}const res3 = g.next(); // 30
console.log(res3); // {value: ccc, done: true}
3.可以使用for...of
进行遍历每个状态
function* gen() {console.log(10);yield "aaa";console.log(20);yield "bbb";console.log(30);return "ccc";
}const g = gen();
for (const i of g) {console.log(i);
}
4.通过next
方法,可以传入参数到生成器函数
注:第一个next方法传入的参数不会生效
function* gen() {const res1 = yield;console.log(res1);const res2 = yield;console.log(res2);
}const g = gen();
g.next(10); // 无输出
g.next(20); // 20
g.next(30); // 30
分析:
1.执行第一个next时,碰到第一个yield停下来了,还没有执行赋值操作
2.执行第二个next时,将传入的参数20赋值给了res1,接着碰到第二个yield停下
3.执行第三个next时,将传入的参数30赋值给了res2,接着走到函数结束
8. Proxy和Reflect
8.1 Proxy
代理(Proxy ):作用是在对象和对象的属性值之间设置一个代理,获取该对象的值、设置该对象的值以及实例化等操作,都会被拦截住。经过这一层,我们可以统一处理,我们可以认为它就是代理器。
拦截:获取和修改数据时会进行拦截,用于脏数据检查。
1.es5 拦截方法:Object.defineProperty()
Object.defineProperty(obj, prop, descriptor)
:
obj
:要被修改拦截的对象prop
:要被修改拦截的属性descriptor
:当访问属性时,会调用get函数;当属性值被修改时,会调用set函数。
缺点:
1.一次只能拦截一个属性
2.只能拦截对象
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><p>Hello World</p><script>const p = document.querySelector("p");const obj = {};// 为obj对象的data属性设置拦截Object.defineProperty(obj, "data", {get() {return p.innerHTML;},set(value) {p.innerHTML = value;}});</script></body>
</html>
分别输入obj.data
、obj.data='aaa'
、obj.data
,触发 get、set 和 get, 运行结果如下:
2.es6 拦截方法:Proxy(target, handler)
Proxy(target, handler)
:
target
:要被修改拦截的对象handler
:执行各种操作时代理的行为
优点:
1.一次可以拦截多个属性
2.可以拦截任何类型的对象,包括数组、函数等
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><p>Hello World</p><script>const p = document.querySelector("p");const obj = {};// 为obj对象创建一个代理const proxy = new Proxy(obj, {get(target, key) {return target[key];},set(target, key, value) {// 访问data属性时,修改dom元素if (key === "data") {p.innerHTML = value;}target[key] = value;}});</script></body>
</html>
操作obj对象,运行结果如下:
操作proxy对象,运行结果如下:
8.2 Reflect
反射(Reflect):用于获取目标对象的行为,它与Object类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与proxy handlers 的方法相同。
1.代替Object的某些方法
const obj = {};
Reflect.defineProperty(obj, "name", {value: "Bill"
});
2.修改某些Object方法的返回结果
// Object.defineProperty返回值是对象,只能使用try...catch做异常处理
try {Object.defineProperty(target, property, attributes);// success
} catch (e) {// fail
}// Reflect.defineProperty方法的返回值为Boolean值,可以使用if...else做异常处理
if (Reflect.defineProperty(target, property, attributes)) {// success
} else {// fail
}
3.命令式写法改为使用函数写法
// 命令式写法
const obj = { name: "Bill" };
console.log("name" in obj); // true
delete obj.name;
// Reflect函数写法
const obj = { name: "Bill" };
console.log(Reflect.has(obj, "name")); // true
Reflect.deleteProperty(obj, "name");
4.配合Proxy使用,反射到代理对象原来的默认行为上
const s = new Set();
const proxy = new Proxy(s, {get(target, key) {const value = Reflect.get(target, key); // 等价于const value = target[key]// 判断如果是方法,修正this指向if (value instanceof Function) {return value.bind(target);}return value;},set(target, key, value) {Reflect.set(target, key, value); // 等价于target[key] = value}
});
注:还可以和扩展运算符配合使用,将以上的
get
和set
方法,改为Reflect.get(...arguments)
和
Reflect.set(...arguments)
在控制台输入内容,运行结果如下:
9. Promise
Promise:是异步编程的一种解决方案,比传统的解决方案回调函数,更合理和更强大。
Promise的作用: 解决异步回调地狱的问题。
回调地狱:当一个回调函数嵌套一个回调函数的时候,就会出现一个嵌套结构,当嵌套多了就会出现回调地狱的情况。
例如发送三个ajax请求:
- 第一个正常发送
- 第二个请求需要第一个请求的结果中某一个值作为参数
- 第三个请求需要第二个请求的结果中某一个值作为参数
Promise的状态:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):意味着操作成功完成。
- 已拒绝(rejected):意味着操作失败。
- 这三种状态的变化途径只有两种:从待定到已兑现、从待定到已拒绝。
- 一旦状态发生变化,就凝固了,不会再有新的状态变化,这是Promise(承诺)这个名字的由来,一旦承诺生效,就不能再改变了。
Promise构造器语法:
new Promise(executor)
1.Promise的基础示例
const promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("success");}, 1000);
});promise.then(res => {console.log(res); // success
});
当执行了resolve方法,则会执行第一个回调函数then方法
2.异步操作成功执行resolve
方法,然后回调then
方法,异步操作失败执行reject
方法,然后回调catch
方法
1.resolve方法传入的参数,作为then方法的入参
2.reject方法传入的参数,,作为catch方法的入参
const promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("success");reject("failed");}, 1000);
});promise.then(res => {console.log(res); // success}).catch(err => {console.log(err); // failed});
运行结果:
分析:先调用了 resolve 方法,导致状态从待定到已兑现,然后状态发生凝固,后续reject方法不再执行。
3.链式调用,解决回调地狱问题
链式调用图解:
const promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("success");reject("failed");}, 1000);
});promise.then(res => {console.log(`first ${res}`); // first successreturn res;}).then(res => {console.log(`second ${res}`); // second success}).catch(err => {console.log(err);});
分析:
- 先调用了resolve,然后执行第一个then方法,promise对象的状态从待定到已兑现。
- 第一个then方法执行完成后,又返回了一个新的promise对象(同时返回值也会作为第二个then方法的入参),新的promise对象继续执行了第二个then方法,然后新promise对象的状态也从待定到已兑现。
4.Promise.all()
:等待所有传入的 promise 都变为完成状态后,再执行回调
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve(1000);}, 1000);
});const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve(2000);}, 2000);
});const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve(3000);}, 3000);
});// p1, p2, p3都执行了resolve后,调用then
Promise.all([p1, p2, p3]).then(res => {console.log(res); // [1000, 2000, 3000]}).catch(err => {console.log(err);});
5.Promise.race()
:所有传入的 promise 中,先变为完成状态的 promise 执行回调
// p1等待一秒,最先执行完毕
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve(1000);}, 1000);
});const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve(2000);}, 2000);
});const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve(3000);}, 3000);
});// p1, p2, p3第一个执行resolve的,调用then
Promise.race([p1, p2, p3]).then(res => {console.log(res); // 1000}).catch(err => {console.log(err);});
10. Async和Await
Async + Await
是Promise + Generator
的语法糖,它可以使得Promise的书写更为简单,可以使用同步的方式,来执行异步操作。
async 和 await:
- async 使函数返回 Promise
- await 使函数等待 Promise
10.1 Async
1.函数前加上关键字 async
,使函数返回 promise 对象
async function fn() {return "Hello World"; // 等价于return Promise.resolve("Hello World");
}const res = fn();
console.log(res); // Promise {<fulfilled>: 'Hello World'}
2.return的值为promise对象时,异步操作成功执行resolve
方法,然后回调then
方法,异步操作失败执行reject
方法,然后回调catch
方法
1.resolve方法传入的参数,作为then方法的入参
2.reject方法传入的参数,,作为catch方法的入参
async function fn() {return new Promise((resolve, reject) => {resolve("success");// reject("failed");});
}const promise = fn();
promise.then(res => {console.log(res); // success}).catch(err => {console.log(err); // failed});
10.2 Await
await
使函数等待 promise
注:await 关键字只能在 async 函数中使用
1.不使用await
,不会等待promise
function fn() {return new Promise((resolve, reject) => {setTimeout(() => {console.log(1);resolve(2);}, 2000);});
}// 不使用await
async function test() {const res = fn();console.log(res); console.log(3);
}test();
运行结果:
分析:
1.未使用await,因为setTimeout是异步的,setTimeout的回调函数还未执行,那么resolve也还没执行到,就已经把promise对象返回了,因此打印出来的res是一个还在pending状态的promise对象。
2.因为setTimeout是异步的,没有阻塞后续代码的执行,所以先打印了3。
3.两秒钟结束后,执行setTimeout的回调函数,打印了1,再执行了resolve方法。
2.使用await
,会等待promise返回
function fn() {return new Promise((resolve, reject) => {setTimeout(() => {console.log(1);resolve(2);}, 2000);});
}// 使用await
async function test() {const res = await fn();console.log(res);console.log(3);
}test();
运行结果:
分析:
1.使用了await,会一直等待promise返回,直到resolve方法执行后,再执行后续代码,因此先执行了setTimeout的回调函数(因为resolve方法在该回调函数中),打印了1
2.执行了resolve,将resolve的结果,返回给res,打印了2
3.再执行后续代码,最后打印了3
3.使用await
,只会等待promise,而不会等待其他的异步
以下代码,使用了await,并不会等待setTimeout先执行回调函数,因为resolve不在setTimeout的回调函数中
function fn() {return new Promise((resolve, reject) => {setTimeout(() => {console.log(1);}, 2000);resolve(2); // 不把resolve放在setTimeout回调函数内});
}// 使用await
async function test() {const res = await fn();console.log(res);console.log(3);
}test();
运行结果:
分析:
1.调用fn时,先执行到了setTimeout,由于它是异步的,其回调函数没有先执行
2.然后执行了resolve方法,将结果返回给了res,打印了2
3.再执行后续代码,最后打印了3
4.两秒钟结束后,执行setTimeout的回调函数,打印了1
11. 类
类:类不是对象,而是对象的模板
11.1 类的定义和使用
类的语法:
class ClassName {constructor() { ... }method_1() { ... }method_2() { ... }method_3() { ... }
}
1.类的定义和使用
- 使用关键字
class
创建一个类 - 通过构造方法
constructor()
给属性赋值 - 创建类方法的语法与对象方法相同
构造方法:
1.创建对象时会自动调用构造方法
2.构造方法用于初始化对象属性
3.如果没有定义构造方法,JS 会添加一个空的构造方法
// 类的定义
class Person {// 构造方法constructor(name, age) {this.name = name;this.age = age;}// 类方法say() {console.log(this.name, this.age);}
}const person = new Person("Bill", 18); // 使用类来创建对象
console.log(person.name); // Bill
console.log(person.age); // 18
person.say(); // Bill 18
2.类可以使用 getter 和 setter
- 在类中添加 getter 和 setter,请使用
get
和set
关键字 - getter/setter 的方法名不能与属性名相同
- 建议使用下划线字符将 getter/setter 与实际属性分开
class Person {constructor(name, age) {this._name = name;this._age = age;}// getterget getName() {return this._name;}// setterset setName(x) {this._name = x;}
}const person = new Person("Bill", 18);
console.log(person.getName); // Bill
person.setName = "Jackson";
console.log(person.getName); // Jackson
11.2 类的继承
类继承:使用类继承创建的类,继承了另一个类的所有方法
1.使用关键字 extends
来继承类
super()
方法引用父类:
1.在constructor
方法中调用super
方法,则调用了父类的 constructor 方法,获得了父级的属性和方法的访问权限
2.在类方法中调用super
方法,则调用了父类的类方法
// 创建一个Person类
class Person {constructor(name, age) {this.name = name;this.age = age;}say() {console.log(this.name, this.age);}
}// 创建一个Student类,继承了Person类
class Student extends Person {constructor(name, age, score) {super(name, age); // 调用父类的constructor方法this.score = score;}
}const student = new Student("Bill", 18, 90);
student.say(); // 调用父类的方法
2.重写方法
- 当子类的方法名与父类的方法名一致时,子类的方法会覆盖父类的方法
- 子类的对象调用该方法时,调用的是子类的方法,而不会调用父类的方法
// 创建一个Person类
class Person {constructor(name, age) {this.name = name;this.age = age;}say() {console.log(this.name, this.age);}
}// 创建一个Student类,继承了Person类
class Student extends Person {constructor(name, age, score) {super(name, age);this.score = score;}// 重写父类的方法say() {console.log(`${this.name}: age is ${this.age}, score is ${this.score}`);}
}const student = new Student("Bill", 18, 90);
student.say(); // Bill: age is 18, score is 90
12. 模块
模块:一个模块(module)就是一个js文件,可以通过export
和import
命令来实现两个模块之间的交互,也就是一个js文件可以引用另一个js文件的内容。
export
:表示当前模块的变量和函数可以被外部访问import
:导入了其它模块的变量和函数到当前模块
注:以前使用
<script src="xxx.js"></script>
的方式来引用js文件,会带来一些问题(如引用的两个js文件有函数名和变量名相同),而通过模块化可以解决这些问题。
12.1 export
1.定义变量和函数的同时就导出
export const name = "Bill";
export const age = 18;export function fn() {console.log("Hello World");
}
2.定义变量和函数后再导出
const name = "Bill";
const age = 18;function fn() {console.log("Hello World");
}export { name, age, fn };
3.使用as
关键字,可以给导出的变量和函数取别名
注:导出的时候取了别名的话,导入时也需要使用导出时的别名
const name = "Bill";
const age = 18;function fn() {console.log("Hello World");
}export { name as gName, age as gAge, fn as gFn };
4.export default
默认导出
- 一个模块中,只能有一个
export default
- 默认导出时可以不需要指定名字
- 导入时不需要使用
{}
,并且可以自己来指定名字
// 默认导出变量
const name = "Bill";
export default { name };
// 默认导出函数
export default function fn() {console.log("Hello World");
}
12.2 import
准备一个test.js
文件,用于导出变量和函数,内容如下:
const name = "Bill";
const age = 18;function fn() {console.log("Hello World");
}export { name, age, fn };
1.在js文件中导入另一个js文件
在test.js
同级目录下,新建一个demo.js
,内容如下:
import { name, age, fn } from "./test.js";console.log(name, age); // Bill 18
fn(); // Hello World
2.在html文件中导入另一个js文件
注:html文件导入js文件时,要设置
script
标签的属性type="module"
,否则会报错
在test.js
同级目录下,新建一个demo.html
,内容如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><script type="module">// 导入test.jsimport { name, age, fn } from "./test.js";console.log(name, age); // Bill 18fn(); // Hello World</script></body>
</html>
3.使用as
关键字,可以给导入的变量和函数取别名
import { name as gName, age as gAge, fn as gFn } from "./test.js";console.log(gName, gAge);
gFn();
4.使用*
和 as
,可以把所有导入变量和函数指定到一个模块对象上
注:使用这种方式导入时,要去掉
{}
import * as obj from "./test.js";console.log(obj.name, obj.age);
obj.fn();
相关文章:
![](https://img-blog.csdnimg.cn/c5b652eba8904ae7a98d606937d112ad.png)
ES6新特性详解
文章目录1. let和const1.1 let声明变量1.2 const声明常量2. 模板字符串3. 解构赋值3.1 数组的解构赋值3.2 对象的解构赋值4. 函数扩展4.1 参数默认值4.2 剩余参数4.3 箭头函数5. 对象扩展5.1 对象简写5.2 属性名表达式5.3 扩展运算符6. Symbol7. Iterator和Generator7.1 Iterat…...
![](https://img-blog.csdnimg.cn/e9d44d73c7dc43388dec36cf4f6567d9.png)
Ubuntu下安装 ntfs-3g
目录1.FAT32、NTFS和exFAT2.ubuntu 安装 ntfs-3g2.1 直接安装2.2 源码安装1.FAT32、NTFS和exFAT U盘在格式化的时候都会有三种格式分别是FAT32、NTFS和exFAT。 FAT32格式 FAT32格式硬盘分区的最大容量为2TB,虽然U盘做不到,但是现在1xTB硬盘都有了&…...
![](https://www.ngui.cc/images/no-images.jpg)
【专业认知】抖音就业 / 保研北大教育学 / 留学南加州EE / 微软就业
2023.2.18 一. 周金辉学长分享——本科经验分享 0 简介 计算机农大本硕 硕士毕业后在抖音公司工作 1 行业前景:计算机专业能做什么? 1.1 计算机行业发展路线 远古时代: 二战开始,计算机技术发展,出现互联网 包…...
![](https://www.ngui.cc/images/no-images.jpg)
【算法题】2 的 n 次幂的背后
前言: 说实话,真的不爱写算法题相关的文章了,觉得没啥意义,但是对这种比较好玩并且简单,学会了就能很好提高算法效率的文章,还是要写一写,不哭不哭,你不会不是你的错,只是…...
![](https://www.ngui.cc/images/no-images.jpg)
【人工智能AI】一、NoSQL 企业级基础入门《NoSQL 企业级基础入门与进阶实战》
写一篇介绍什么是NoSQL的技术文章,分5个章节,每个章节细分到3级目录,重点介绍一下优缺点,适用场景,未来发展趋势等。 一、NoSQL简介 1.1 什么是NoSQL NoSQL(Not only SQL),意思是“…...
![](https://img-blog.csdnimg.cn/0f5595f6cb1e4be197a2fb8940185c0b.png)
Ubuntu安装opencv库3.4.10,并在cmake工程中引入opencv库
Windows下安装不同,Ubuntu安装OpenCV库时,需要事先安装依赖,而且不同OpenCV库所需的依赖可能会有所不同,下面的依赖亲测 3.4.10 和 4.5.5版本的有效,但是4.6以上版本安装可能会报错。 参考链接:https://bl…...
![](https://img-blog.csdnimg.cn/38cfe37407924b50ac66331b4d797796.png)
实现8086虚拟机(四)——mov 和 jmp 指令解码
文章目录mov 指令解码jmp 指令解码这篇文章举例来讲讲 mov 指令和 jmp 指令解码函数的实现,其他的指令解码函数都与这些类似。mov 指令解码 以 mov 指令中的一类:寄存器/内存 到/从 寄存器,来详细说明解码函数的实现。 机器指令格式如下&am…...
![](https://img-blog.csdnimg.cn/dec3b75aa19a476999b835fb4cc4b360.png)
数据库技术-函数依赖、键与约束、范式
一、函数依赖 给定一个x,能唯一确定一个Y,就称x确定Y,或者说Y依赖于x,例如YX*X函数。 函数依赖又可扩展以下两种规则: 部分函数依赖:A可确定C,(A,B)也可确定C,(A,B)中的一部分(即A)可以确定C&a…...
![](https://img-blog.csdnimg.cn/81e31e8ecb5e45b382b21d835d7ef587.png)
shiro CVE-2020-1957
0x00 前言 在之前只是单纯的复现了漏洞,没有记笔记,所以补充了这篇分析笔记。 影响版本:shiro < 1.5.2 0x01 环境搭建 环境用的是:https://github.com/lenve/javaboy-code-samples/tree/master/shiro/shiro-basic 0x02 漏…...
![](https://img-blog.csdnimg.cn/c5614108e1704c60a03591a4e9f870e6.png#pic_center)
RabbitMQ 入门到应用 ( 五 ) 基本应用
6.更多应用 6.1.AmqpAdmin 工具类 可以通过Spring的Autowired 注入 AmqpAdmin 工具类 , 通过这个工具类创建 队列, 交换机及绑定 import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Di…...
![](https://img-blog.csdnimg.cn/img_convert/a4015666ba468e8465fe7882f22308e2.jpeg)
部署dapr的辛酸历程
前言dapr大概的了解,个人理解他就是一个分布式服务的管理,把微服务常用的组件(缓存,消息中间件、分布式锁、安全id4等)和监控以及服务注册、发现等等一系列功能以一个很抽象的方式管理起来。可能我们部署微服务用consul、ocelot、polly套件、…...
![](https://img-blog.csdnimg.cn/beaa3a7242224e82b48635f257c3386c.png)
golang入门笔记——内存管理
文章目录自动内存管理概念自动内存管理-相关概念:追踪垃圾回收:分代GC(Generational GC)引用计数内存分配Go内存分配-分块Go内存分配——多级缓存Go内存管理优化Balanced GC自动内存管理 概念 1.动态内存 程序在运行时根据需求…...
![](https://www.ngui.cc/images/no-images.jpg)
97. 约数之和
Powered by:NEFU AB-IN Link 文章目录97. 约数之和题意思路代码97. 约数之和 题意 假设现在有两个自然数 A和 B,S是 A^B的所有约数之和。 请你求出 S mod 9901的值是多少。 思路 ABA^BAB的约数之和为:sumAB(1p1p12...p1Ba1)(1p2p22...p2Ba2)...sum_{A^B…...
![](https://www.ngui.cc/images/no-images.jpg)
想和20岁的自己说
男生床头千万不要放卫生纸不要叫自己的女朋友早睡,更不能叫她早起,否则有你好受的。成年人的默契:和异性单独出去旅游,如果没有明确拒绝开一间房,那基本上默认后面会发生的事情不要去考验人性,世上99%的人经…...
![](https://img-blog.csdnimg.cn/456fbaa295e14dfeb024b7a3ba897db7.png)
Unit Test and Integration Test
Unit Test and Integration Test Background It is the first time that I try to write an article in English. In the past, I didn’t write test code. Just thinking QA is responsible for testing. As a developer, I don’t need to care about tests. Although I …...
![](https://img-blog.csdnimg.cn/548f2e576c52434fb738812a0406fb99.png)
2022年全国职业院校技能大赛(中职组)网络安全竞赛试题(3)
目录 模块A 基础设施设置与安全加固 (本模块20分) 一、项目和任务描述: 假定你是某企业的网络安全工程师,对于企业的服务器系统,根据任务要求确保各服务正常运行,并通过综合运用用户安全管理与密码策略、…...
![](https://img-blog.csdnimg.cn/img_convert/49690a20f3de0bf376a465c8b392f85a.jpeg)
智慧城市应急指挥中心数字化及城市驾驶舱建设方案
目 录 第一章 项目概述 1.1 项目背景 1.2 项目范围 第二章 建设内容 2.1 三维可视化平台 2.1.1 多源数据接入 2.1.2 可视化编排 2.1.3 三维可视化编辑 2.1.4 空间数据可视化 2.1.5 集成框架支持 2.2 可视化场景定制开发 2.2.1 城市驾驶总舱 2.2.2 城市安全分舱 2.…...
![](https://img-blog.csdnimg.cn/img_convert/506773c22b5cecfa33f72f4d4097840e.png)
HSCSEC 2023 个人练习
😋 大家好,我是YAy_17,是一枚爱好网安的小白。本人水平有限,欢迎各位大佬指点,欢迎关注😁,一起学习 💗 ,一起进步 ⭐ 。⭐ 此后如竟没有炬火,我便是唯一的光。…...
![](https://img-blog.csdnimg.cn/ef4c3a858d1d42caaa4248b8d9f4f187.png)
Android 基础知识4-2.7 RelativeLayout(相对布局)
一、RelativeLayout的概述 RelativeLayout(相对布局)是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。在很多时候,线性布局还不能满足我们的需求,比如,我们在一行(列)上显示多个控…...
![](https://img-blog.csdnimg.cn/img_convert/677306a2a454a2f5ced9e63209041857.png)
关于云计算,我们问了ChatGPT 10个问题
ChatGPT懂云计算吗?前些天,我们问了ChatGPT(非Plus收费版)一些问题。1. 什么是云计算?2. 云计算行业的护城河是什么?3. 什么是云原生?4. 微软Azure与亚马逊AWS的主要区别是什么?5. 为…...
![](https://www.ngui.cc/images/no-images.jpg)
Netty学习笔记1
Netty学习笔记(一) 在的互联网环境下,分布式系统大行其道,而分布式系统的根基在于网络编程,而 Netty 恰恰是 Java 领域网络编程的王者。如果要致力于开发高性能的服务器程序、高性能的客户端程序,必须掌握…...
![](https://www.ngui.cc/images/no-images.jpg)
RISK-V品牌的中国化历程(中)
目录 1.技术优势 出道即巅峰 2.生态布道 品牌根植中国 3.应用场景 加速品牌的商业化运作 生态布道 品牌根植中国 2015年成立非盈利组织RISC-V基金会,目前已吸引全球28个国家327家会员,包括英伟达、联发科、苹果、特斯拉、谷歌、高通、IBM、三星、麻省理…...
![](https://img-blog.csdnimg.cn/49520c6d42644988930a2419a8c4664d.png#pic_center)
2023.02.19 学习周报
文章目录摘要文献阅读1.题目2.摘要3.介绍4.本文贡献5.方法5.1 Local Representation Learning5.2 Global Representation Learning5.3 Item Similarity Gating6.实验6.1 数据集6.2 结果7.结论深度学习1.对偶问题1.1 拉格朗日乘数法1.2 强对偶性2.SVM优化3.软间隔3.1 解决问题3.…...
![](https://img-blog.csdnimg.cn/20190602114730587.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzYxMDY5OA==,size_16,color_FFFFFF,t_70)
枚举类的使用方法
一、理解枚举类型 枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。下面先来看看如何写…...
![](https://img-blog.csdnimg.cn/7da65dfd059d4f13b61d0f76a085d078.png)
.NET3.5安装步骤及相关问题。
.NET3.5全称 Microsoft.NETFramework3.5 最新版本-.NET4.8 第一步打开控制面板 windows系统打开控制面板 选择程序 选择.NET3.5安装。 可能会出现问题。 解决方案: 报错代码80240438的常用解决办法: 方法一:检测windows update servic…...
![](https://img-blog.csdnimg.cn/9c23891469734777bb4bd278d097739c.png)
联想M7268激光打印机开机红绿灯双闪报错不打印
故障现象: 一台联想M7268激光打印机开机后电源键、复印键一起双闪,电源键闪红灯、复印键闪绿灯; 检测维修: 根据闪灯故障判断如果无卡纸异常情况下可能是激光器故障,因为以前曾经维修过一台一模一样的机器故障基本相同,先打开机器吧,把硒鼓拿出来先看看有没有卡纸,进纸…...
![](https://www.ngui.cc/images/no-images.jpg)
产品经理知识体系:7.web和app产品需求设计
web和app产品需求设计 思考 笔记 web产品设计 一、交互设计 1.以用户为中心的设计:功能、体验、用户; 将产品功能转化成用户的体验,功能和体验的结合。 2.交互设计模式 交互逻辑 信息结构 信息内容 界面结构 导航设计 二、视觉设计 元素的…...
![](https://www.ngui.cc/images/no-images.jpg)
强化学习概述
一、Modelfree 和 Modelbased Modelfree:不需要理解环境 Modelbased:需要理解环境,并且为环境建立模型 Model-free 中, 机器人只能按部就班, 一步一步等待真实世界的反馈, 再根据反馈采取下一步行动. 而 model-based, 他能通过想象来预判断接…...
![](https://img-blog.csdnimg.cn/0048b8399d4b47478591b768bc265078.png)
NO.1嵌入式入门笔记:常用命令记录
一、前言 Linux文件目录: Linux Shell: 它负责接收用户的输入,根据用户的输入找到其它程序并运行。比如我们输入“ls”并回车时,shell 程序找到“ls”程序并运行,把结果打印出来。Shell有多种实现,我们常用…...
![](https://www.ngui.cc/images/no-images.jpg)
Shell编程
typora-copy-images-to: pictures typora-root-url: pictures 文章目录typora-copy-images-to: pictures typora-root-url: pictures本节课程目标语法和选项语法和选项3. sort工具语法和选项5.tee工具6.diff工具语法和选项7. paste工具8. tr工具语法和选项小试牛刀二、bash的特…...
![](/images/no-images.jpg)
自己做网站在线看pdf/百度智能云官网
http://www.cnblogs.com/wenjiang/p/3180324.html handleMessage 好用转载于:https://www.cnblogs.com/userbibi/p/3357501.html...
![](/images/no-images.jpg)
新公司网站建设流程/电子商务推广方式
依赖包安装 # 安装 myjs-common 包 npm install myjs-common1.0.0格式器表达式 YEAR_FORMAT: 年格式化-yyyyMONTH_FORMAT: 月格式化-yyyy-MMDATE_FORMAT: 日期格式化-yyyy-MM-ddHOUR_FORMAT: 时格式化-yyyy-MM-dd HHMINUTE_FORM…...
![](/images/no-images.jpg)
深圳企业招聘信息网官网/seo品牌
Java 基于aspose将word转换pdf格式 网上有很多将word文档转换成pdf格式的例子,如windows平台安装插件,或者linux服务器上安装插件,或者JDK中加入dll等方式,我个人感觉局限性比较大。如何说? 是不是我在另一个电脑上操…...
![](/images/no-images.jpg)
怎么免费下wordpress/国外网站seo免费
vue弹窗加校验点击添加专区的按钮出现添加专区的弹窗根据elementui里面的dialog和form表单写的<div slot"setting"><el-button type"primary" click"addSub true">添加专区</el-button> </div>addSub是控制弹窗的显示隐…...
![](http://blog.51cto.com/attachment/200909/200909181253243852578.jpg)
广州商务网站建设/最近最新新闻
这是我的祖国,我们的祖国,尽管现在还有许多不尽人意的地方,但我爱我的祖国,我们都爱我们的祖国!!我们的祖国一定会更加强大!!! 本文转自ycrsjxy51CTO博客,原文…...
![](https://img-blog.csdnimg.cn/07ee404dd1e74977a4f44e9e8b42de81.png)
怎样宣传一个网站/昆明做网站的公司
蓝桥杯练习系统:http://lx.lanqiao.cn/problemset.page?codeBASIC-&userid509443 问题描述 153是一个非常特殊的数,它等于它的每位数字的立方和,即153111555333。编程求所有满足这种条件的三位十进制数。 输入格式: 输入一…...