值、常量与契约
什么可以称为值?
- 值: 任何可以赋给变量的内容;
- 范围: 数字、不可变对象、函数、数组和
undefined都是值;
5;
Object.freeze({ name: "John", age: 30 });
(a) => a;
[1];
undefined;
常量保证了什么?
- 常量: 定义后不能重新赋值的变量;
- 替换: 当指向的值也稳定时,可用该值替换常量引用;
- 注意:
const只禁止重新绑定;对象内容需额外使用不可变约束;
const five = 5;
const john = Object.freeze({ name: "John", age: 30 });
john.age + five === { name: "John", age: 30 }.age + 5;
常量函数、函子和单子怎样忽略变换?
- 常量函数: 保存第一个参数并忽略后续参数;
- 常量函子:
map不变换内部内容; - 常量单子:
chain不变换内部内容;
const constant = (a) => () => a;
[1, 2].map(constant(0)); // [0, 0]
Constant(1).map((n) => n + 1); // Constant(1)
Constant(1).chain((n) => Constant(n + 1)); // Constant(1)
契约怎样约束运行时输入与输出?
- 契约: 声明函数或表达式在运行时承担的义务与提供的保证;
- 违反: 输入或输出不满足规则时立即报告错误;
const numberContract = (input) => {
if (typeof input === "number") return true;
throw new Error("Contract violated: expected number");
};
const addOne = (num) => numberContract(num) && num + 1;
addOne(2); // 3
addOne("2"); // 抛出契约错误
契约与类型签名各自工作在哪一层?
| 机制 | 作用时机 | 主要作用 |
|---|---|---|
| 类型签名 | 阅读/检查 | 描述输入与返回值的形状 |
| 契约 | 运行时 | 检查真实值是否履行规则 |