本文介绍结构赋值、运算符的扩展、装饰器新旧版本的基本用法。
Iterator
接口就可以结构 类遍历器对象也可以undefined
才触发默认值注意点:
注: 函数参数也是对象, 因此可以使用对象的方式进行解构
boolean
string
number
BigInt
Symbol
只要有包装对象(排除了 null
undefined
)就可以进行解构,获取原型链上的方法或属性。
**
**=
?.
?.[]
?.()
注意事项
?.
运算符的场合,不应该使用圆括号。??
他的行为类似 ||
但只有null
或undefined
,才会返回右侧的值?.
使用||=
&&=
??=
bash#!/usr/bin/env node
用途
其实装饰器从ES6诞生开始就有,一直到现在才进入第三阶段(候选),不过也就差最后一步了,由于很多项目都用到装饰器,这一块不得不认真学。
json{
// ...
"dependencies": {
"@babel/cli": "^7.22.10",
"@babel/core": "^7.22.10",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/preset-env": "^7.22.10",
"core-js": "3"
},
"browserslist": [
"chrome >= 100"
]
}
jsmodule.exports = {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: {
version: 3,
proposals: true, // 默认值是false, 对stage阶段的全局对象上的方法打补丁
},
},
],
],
plugins: [
[
"@babel/plugin-proposal-decorators",
{
legacy: true,
},
],
],
};
sh#!/bin/bash
run() {
local name=$1
eval "npx babel $1 --out-file dist/$1"
eval "node dist/$1"
}
run $1
执行命令 sh build.sh 1.js
js@decorator
class A {}
// 等价于
A = decorator(A) || A
class MyReactComponent extends React.Component {}
connect(mapStateToProps, mapDispatchToMap)(MyReactComponent);
// 使用装饰器优化React-Reduce代码
@connect(mapStateToProps, mapDispatchToMap);
target
值为被修饰的类descriptor
注意: 装饰器不能修饰函数, 因为函数声明语句存在提升。应采用高阶函数方式替代
js@decorator1
@decorator2
class A {
@decoratorMethod1
@decoratorMethod2
say(text) {
console.log('A.prototype.say()', text);
}
}
decoratorMethod2
decoratorMethod1
decorator2
decorator1
装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。 这意味着什么呢?
kind
的值是啥含义
kind 枚举值 | 含义 | 对value的影响 |
---|---|---|
class | 类装饰器 | 对应的类 |
method | 方法装饰器 包括原型方法和静态方法 | 对应的方法` |
field | 属性装饰器 | value 为 undefined |
getter | 取值器装饰器 | value 为 取值器 |
setter | 存值器装饰器 | value 为 存值器 |
accesser | 它是存取器的简写 | value 为 一个对象,内含取值器和存值器 |
jstype ClassDecorator = (value: Function, context: {
kind: "class";
name: string | undefined; // 如果被装饰的类是一个匿名类时其值为undefined
addInitializer(initializer: () => void): void;
}) => Function | void;
tstype ClassMethodDecorator = (value: Function, context: {
kind: "method";
name: string | symbol;
access: { get(): unknown };
static: boolean;
private: boolean;
addInitializer(initializer: () => void): void;
}) => Function | void;
addInitializer()
package.json
json{
"dependencies": {
"@babel/cli": "^7.22.10",
"@babel/core": "^7.22.10",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/preset-env": "^7.22.10"
},
"browserslist": [
"chrome >= 100"
]
}
@babel/plugin-proposal-decorators
的配置即可。sh build.sh 1.js
示例
jsfunction logged(value, { kind, name }) {
if (kind === "class") {
return class extends value {
constructor(...args) {
super(...args);
console.log(`constructing an instance of ${name} with arguments ${args.join(", ")}`);
}
}
}
}
@logged
class C {}
new C(1);
// constructing an instance of C with arguments 1
类装饰器实际上执行的是下面的语法。
jsclass C {}
C = logged(C) ?? C
function trace(value, context) {
return function(...args) {
console.log('trace hello ', this.name);
value.call(this, ...args);
}
}
class Person {
constructor(name) {
this.name = name;
}
@trace
hello() {
console.log(`Hi ${this.name}!`)
}
}
const robin = new Person('Robin');
console.log(robin.hello());
// trace hello Robin
// Hi Robin!
方法装饰器
undefined
, 否则报错undefined
则使用原方法示例1 webComponents
jsfunction customElement(name) {
return function(value, context) {
context.addInitializer(() => {
customElements.define(name, this);
})
}
}
@customElement('my-element');
class MyElement extends HTMLElement { }
示例2: bound
jsclass C {
message = 'hello';
@bound
m() {
console.log(this.message)
}
}
function bound(value, {addInitializer, name}) {
addInitializer(function() {
this[name] = this[name].bind(this)
})
}
var c = new C();
const {m} = c;
console.log(m());
目前core-decorators.js
采用的是老的装饰器语法实现的
@autobind
@readonly
@override
@deprecate
以下内容挪到了其他文章中讲解
class语法
class继承
《JavaScript面向对象》async函数
Generator
for await..of
《JavaScript异步编程》import
export
《JavaScript模块化》本文作者:郭敬文
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!