// 判断 key 是否是 Symbol if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { return res }
// 如果可读,追踪 if (!isReadonly) { track(target, TrackOpTypes.GET, key) }
// 如果是浅层响应,直接返回得到的值 if (shallow) { return res }
// 判断是否 Ref if (isRef(res)) { // ref unwrapping - does not apply for Array + integer key. const shouldUnwrap = !targetIsArray || !isIntegerKey(key) return shouldUnwrap ? res.value : res }
if (isObject(res)) { // Convert returned value into a proxy as well. we do the isObject check // here to avoid invalid value warning. Also need to lazy access readonly // and reactive here to avoid circular dependency. return isReadonly ? readonly(res) : reactive(res) }
const effects = newSet<ReactiveEffect>() const computedRunners = newSet<ReactiveEffect>() const add = (effectsToAdd: Set<ReactiveEffect> | undefined) => { if (effectsToAdd) { effectsToAdd.forEach(effect => { if (effect !== activeEffect || !shouldTrack) { if (effect.options.computed) { computedRunners.add(effect) } else { effects.add(effect) } } else { // the effect mutated its own dependency during its execution. // this can be caused by operations like foo.value++ // do not trigger or we end in an infinite loop } }) } }
// 如果当前触发类型为 CLEAR if (type === TriggerOpTypes.CLEAR) { // collection being cleared // trigger all effects for target depsMap.forEach(add) } elseif (key === 'length' && isArray(target)) { depsMap.forEach((dep, key) => { if (key === 'length' || key >= (newValue asnumber)) { add(dep) } }) } else { // schedule runs for SET | ADD | DELETE if (key !== void0) { add(depsMap.get(key)) } // also run for iteration key on ADD | DELETE | Map.SET const isAddOrDelete = type === TriggerOpTypes.ADD || (type === TriggerOpTypes.DELETE && !isArray(target)) if ( isAddOrDelete || (type === TriggerOpTypes.SET && target instanceofMap) ) { add(depsMap.get(isArray(target) ? 'length' : ITERATE_KEY)) } if (isAddOrDelete && target instanceofMap) { add(depsMap.get(MAP_KEY_ITERATE_KEY)) } }
// Important: computed effects must be run first so that computed getters // can be invalidated before any normal effects that depend on them are run. computedRunners.forEach(run) effects.forEach(run) }
// boolean let isDone: boolean = false; // number // JavaScript 和 TypeScript 中的数字不是浮点类型 floating point 就是大整数类型 BigInteger let decLiteral: number = 6; let bigLiteral: number = 100n; // string let name: string = 'bob'; // Array let list: number[] = [1,2,3]; let list: Array<number> = [1,2,3]; // Tuple // 元组类型要求值类型、顺序和个数一一对应 let tuple: [string, string] = ['string', 'string']; // enum enum Color {Red = 0, Green, Blue} let c: Color = Color.Green; // Any let source: any = 4 // Void let unusable: void = undefined; // Null & Undefined let u: undefined = undefined; let n: null = null; // Never functionerror(message: string): never{ thrownewError(message); } // 类型断言 // 明确知道值的类型时可使用类型断言 let strValue: any = 'str'; let length: number = (<string>strValue).length; let length: number = (strValue asstring).length
变量声明
var
可以通过 var 关键字定义变量,但是 var 声明可以在包含它的函数、模块、命名空间或全局作用域内部任何位置被访问,包含它的代码块对此没有影响,这可能会引发一些错误,比如多次声明同一个变量并不会报错。
let
当用 let 声明一个变量,它使用的是词法作用域或块作用域。不同于使用 var 声明的变量那样可以在包含它们的函数外访问,块作用域变量在包含它们的块之外是不能访问的。
const
const 拥有与 let 相同的作用域规则,但是声明的变量被赋值后不能再改变。
每次进入一个作用域时,它创建了一个变量的环境,就算作用域内代码已经执行完毕,这个环境与其捕获的变量依然存在。当 let 声明出现在循环体里时拥有完全不同的行为,不仅是在循环里引入了一个新的变量环境,而是针对每次迭代都会创建这样一个新作用域。
// 如果 x 要兼容 y, y 至少要与 x 拥有相同的属性 let x = { name: 'x' }; let y = { name: 'y', alias: 'Y' }; x = y; y = x; // Property 'alias' is missing in type '{ name: string; }' but required in type '{ name: string; alias: string; }
函数的类型兼容性
如果函数 x 要兼容函数 y,那么 x 至少要与 y 具有相同的参数并且返回值类型相同。
1 2 3 4 5 6 7 8
let funCom = (x: number, y: number) => x + y; let funAbc = (x: number, y: number) => [x, y]; let funSub = (x: number) => x; let funDef = (x: number, y: number) => x * y; funCom = funSub; funSub = funCom; // Type '(x: number, y: number) => number' is not assignable to type '(x: number) => number' funCom = funAbc; // Type '(x: number, y: number) => number[]' is not assignable to type '(x: number, y: number) => number'.Type 'number[]' is not assignable to type 'number' funCom = funDef;