类、符号、对象和装饰器
类
-
类的使用
// 类的声明 class Fruit { } // 等价于构造函数的声明 function Fruit() { }
注意: 类的声明与构造函数的声明不同点:类的声明没有作用域的提前
-
类的属性和方法
-
constructor方法:在类的实例化的时候,constructor方法会自动调用。并且实例化时的参数都会被constructor方法接收
class Log { constructor(...args) { console.log(args); } } new Log('a', 'b', 'c') // ['a', 'b', 'c']
-
get 关键字
class Counter { constructor(start) { this.count = start; } get next() { return this.count++ } } // get next(){}:get关键词修饰的方法表示Counter实例会有一个next属性。访问该属性时会返回该方法的调用结果 const counter = new Counter(2); console.log(counter.next); // 2 console.log(counter.next); // 3 console.log(counter.next); // 4
-
set关键字:set关键词修饰的方法表示LocalStorage实例设置data属性时。设置该属性时会返回该方法的调用结果
class LocalStorage { constructor(key) { this.key = key; } get data() { return JSON.parse(localStorage.getItem(this.key)); } set data(data) { localStorage.setItem(this.key, JSON.stringify(data)); } } const ls = new LocalStorage('groceries'); ls.data = ['apples', 'bananas', 'grapes'] console.log(ls.data); // ['apples', 'bananas', 'grapes']
-
static关键字
-
static关键字修饰的方法表示这个方式是静态方法。
-
static关键字可以修饰其他关键字。static get\static set 表示是静态属性存取器
-
注意class 没有静态属性,只有静态方法。
class MathHelper { static sum(...numbers) { return numbers.reduce((a,b) => a+b) } } console.log(MathHelper.sum(1,2,3,4,5)); // 15
-
-
-
类的继承: 关键字extends
在constructor函数中调用super。可以实现继承父类。super中接受的参数传递到父类的构造函数或class中。父类中的方法也可以使用super.方法名的形式调用。
class Fruit { constructor(type, weight) { this.type = type; this.weight = weight; } chop() { console.log(this.type, this.weight); } } class Banana extends Fruit { constructor() { super('banana', 105); } slice(){ this.pieces = 12; super.chop(); return 111 } } const banana = new Banana(); banana.slice() // banana 105
符号
符号是ES新增的基本值类型,是JS中第7中数据类型。
-
本地符号
-
符号的使用
const first = Symbol()
-
创建符号时添加描述或说明
const first = Symbol('my first')
-
符号是独一无二的,即使创建符号时,两者的描述相同
Symbol('my first') === Symbol('my first') /// false
-
typeof 符号
typeof Symbol('my first') // symbol
-
符号可以用作对象的属性名,访问符号对应的值时,必须使用同样的符号
const weapon = Symbol('weapon'); const character = { name: 'Penguin', [weapon]: 'umbrella', } console.log(Object.getOwnPropertySymbols(character[weapon]); // 'umbrella'
-
传统方法【for…in,Object.keys,Object.getOwnPropertyNames】从对象读取属性名时,无法获取符号类型的属性名。
-
获取对象中用作属性名的符号值:Object.getOwnPropertySymbols
const weapon = Symbol('weapon'); const character = { name: 'Penguin', [weapon]: 'umbrella', } console.log(Object.getOwnPropertySymbols(character)); // [Symbol(weapon)]
-
-
符号的实际用法
JavaScript库可以用**符号**将对象映射到DOM元素上。之前的方法:在DOM元素上添加一个指向API的属性,但这样做会污染DOM元素。而且还要小心其他库使用这个属性,否则会导致冲突。
使用**符号**的好处是符号是独一无二的,不用担心污染DOM元素,且符号是独一无二的,不用担心与其它库产生冲突。
// 如果el元素存在日历API,则返回。如果不存在,则给el元素赋予日历API function createCalendar(el) { if(cache in el) { // 检测Symbol值cache是否存在于el元素中 return el[cache] // 直接使用cache,避免重新实例化 } const api = el[cache] = { // 在这里编写日历API } return api }
对象的内置改进
-
使用Object.assign扩展对象:使用方式为Object.assign(target,…source);每个source都会将自己本身的值复制到target中。为了不影响target原对象,一般都会设置target为{}。因此Object.assign的使用方式为
Object.assign({}, source1, source2,[...source3]);
-
Object。setProtorypeOf,设置一个对象的原型
const baseCat = {type: 'cat', legs: 4}; const cat = Object.create(baseCat); // cat: {},原型为baseCat。创建了一个空对象,并为其指定原型。 cat.name = 'Milanesita'; const baseCat = {type: 'cat', legs: 4}; const cat = Object.setPrototypeOf({name: 'Milanesita'}, baseCat); // cat: {name: 'Milanesita'},原型为baseCat。创建了一个对象并为它赋值,并为其指定原型。 // 两者的区别:create只能在创建新对象时为其指定原型。而setPrototypeOf可以改变任意对象的原型