典型错误一:无法掌握的Future 典型错误信息:NoSuchMethodError: The method 'markNeedsBuild' was called on null....典型错误二:Navigator.of(context) 是个 null 典型错误信息:NoSuchMethodError: The method 'pop' was called on null....典型错误信息: Failed assertion: boolean expression must not be null NoSuchMethodError: The method '>' was called...NoSuchMethodError: The method '+' was called on null....NoSuchMethodError: The method '*' was called on null. 示例代码 这种错误,较常发生在使用服务端返回的数据model时。
场景 我们考虑一下下边的代码会输出什么。 import { observe } from "./reactive"; import Watcher from "....但从代码来看 updateComponent 函数中由于 data.ok 为 false,data.text 对输出没有任何影响,这次执行其实是没有必要的。...保存 Watcher 所影响的所有 Dep 对象,当重新收集 Watcher 的前,把当前 Watcher 从记录中的所有 Dep 对象中移除。...增量式移除,重新收集依赖时,用一个新的变量记录所有的 Dep 对象,之后再和旧的 Dep 对象列表比对,如果新的中没有,旧的中有,就将当前 Watcher 从该 Dep 对象中移除。...* Will be called by the scheduler. */ run() { this.get(); } } 测试 回到开头的代码
,从此以后room不允许为null var room: Room = Room() private fun checkRoom() { // 当把null赋给room时,...size > 0) { Log.d("TAG", "-->> 房间数不是0") } 编译器会告诉我们:当roomList为null的时,它的size返回就是"null",但是"null...= null)这种Java常见语句才能避免异常吗? 不过Kotlin不会让程序出现这种啰嗦的代码,所以里面提供了对象A ?: 对象B表达式, ?...这里的 * 就是 展开操作符,在 Java 中是没有 展开操作符 的。...3、会根据 val 和 var 关键字来生成 setter、getter 方法,var 表示该属性可以修改;val 表示该属性不能被修改 class Person(val name: String)
(length)) ctx.length = length } return res.end() } // status body if (body == null) {...当一个中间件中调用next方法后会把index标记为当前的索引,如果一个中间件多次调用next方法,那么由于第一次调用是index会标记为i,那么第二次调用的时候i和index是相等的,也就是第二次的时候会走...每次调用的时候根据索引获取当前要执行的中间件函数,在第18行会执行当前中间件,并把下一个dispatch当作第二个参数next传入到下一个中间件中。...当执行到最后一个中间件的时候,设置fn = next由于Application代码的第52行并没有传递第二个参数,所以此时next是undefined,那么compose中将会走第16行if (!...如果传递了函数那么会执行传入的函数,当此函数中调用next以后,由于索引已经超过了middleware的长度,所以下次函数执行事也会走第16行的逻辑。
use 在Koa中,一切都是中间件,这个是它一个非常好的思想,有它的优势也有它的问题,我之后再去说。use这个api就是我们经常会用到的设置中间件的api,内部的代码实现也是很简单的。...这样的会带来一些性能问题。之后再koa-router中我们去详细看一下性能问题。...如果在我们没有设置body的情况下,默认就会返回404。当所有中间执行完毕,就会执行context中的respond函数。...(length)) ctx.length = length; } return res.end(); } // status body if (null == body)...304,会主动将body清空 到这里基本上就是koa的源码阅读。
当 app.proxy 是 true 时支持 X-Forwarded-Proto protocol 返回请求协议,https 或 http。...当 app.proxy 是 true 时支持 X-Forwarded-Proto host 获取当前主机(hostname:port)。..., 如果没有返回false, 有则返回socket.writable request和response中每个属性get和set的定义以及方法的实现多数比较简单直观,如果对每个进行单独分析会导致篇幅过长...onerror(err) { // 没有错误时什么也不做 if (null == err) return; // err不是Error实例时,使用err创建一个Error实例...可以看到,不管是否使用new关键字,该函数总是会返回一个实例。 function Delegator(proto, target) { if (!
当我们编写 Dart 代码时,「类型检查器」会确保我们不能编写下面这样的代码: int age = "hello world"; // A value of type `String` can't be...called on null....; // NoSuchMethodError: 'Null Value>' 所以,当断言错误时,! 将引发运行时异常。 有时我们需要使用返回可空值的函数: String?...如果知道可以为空的表达式不会是null,则可以使用!运算符将其分配给不可为空的变量。 非空和空的一些使用技巧 在dart中我们一定要添加对null的检查,这样我们的代码才能更健壮。...[0]; } late关键词 late关键字在「第一次读取」时初始化变量,而不是在「创建」时初始化。
vue 初始化的时候 watcher 构造函数通过 Object.defineProperty 方法对 data 属性进行递归遍历,设置 get、set,初始化编译的时候会触发 getter 函数,进行依赖收集...改变数据的时候会触发 set, 执行 notify 方法,调用 dep 中 watcher 对象的 update 方法,update 方法将 watcher 添加到 watcher 队列中, 通过调用.../setters const getter = property && property.get //尝试拿到该对象原生的get属性,保存到getter中 const setter = property...getter || setter) && arguments.length === 2) { //如果getter不存在或者setter存在,且参数只有两个 val = obj[key] //则直接通过...== value)) { //如果value没有改变就直接返回 return } /* eslint-enable no-self-compare */
,动态计算队列的长度,没有缓存长度,是因为在执行现有 watcher 期间队列中可能会被 push 进新的 watcher */ for (index = 0; index length... watcher 会被触发,访问 this.computedProperty 时也会触发 watcher */ export default class Watcher { vm: Component...* 因为触发更新说明有响应式数据被更新了,但是被更新的数据虽然已经经过 observe 观察了,但是却没有进行依赖收集,所以,在更新页面时,会重新执行一次 render 函数,执行期间会触发读取操作,这时候进行依赖收集...$watch 或者 watch 选项时可以传一个 sync 选项 * 当为 true 时在数据更新时该 watcher 就不走异步更新队列,直接执行 this.run * 方法进行更新... * 这个属性在官方文档中没有出现 */ this.run() } else { /** * 更新时一般都这里,将 watcher
第 2 点就迎刃而解了,当修改数据的时候将保存起来的函数执行一次即可。...getter || setter) && arguments.length === 2) { val = obj[key]; } Object.defineProperty...保存当前正在执行的函数 为了保存当前的函数,我们还需要写一个 Watcher 类,将需要执行的函数传入,保存到 Watcher 类中的 getter 属性中,然后交由 Watcher 类负责执行。...getter || setter) && arguments.length === 2) { val = obj[key]; } /******************...总 image-20220329092722630 先从整体理解了响应式系统的整个流程: 每个属性有一个 subs 数组,Watcher 会持有当前执行的函数,当读取属性的时候触发 get ,将当前
getter || setter) && arguments.length === 2) { val = obj[key] } // 对 obj[key] 进行观察,保证对象中的所有 key...上面的代码中,在 Observer 类构造函数执行时创建了一个 new Dep(),之后在定义对象的响应式属性时,也为 Object 的 key 创建一个依赖类 const dep = new Dep(...一个组件渲染时创建一个 watcher。 或者一个表达式创建一个 Watcher ,当表达式发生改变时触发调度。.../** * Watcher 解析一个表达式,收集依赖,当表达式发生改变时触发调度。Watcher 类用于 $watch() api 和指令。...* Will be called when a dependency changes. */ // 订阅者接口,当依赖改变时将会被调用 update () { /* istanbul
我们知道 JavaScript 是弱类型的语言,所以我们在写代码的时候容易出现一些始料未及的问题。也正是因为这个问题,才出现了 Flow 这个静态类型检查工具。...其实 Vue 的双向绑定机制采用数据劫持结合发布/订阅模式实现的: 通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调...在读写访问器属性的值的时候,会调用相应的 getter 和 setter 函数,而我们的 vue 就是在 getter 和 setter 函数中增加了我们需要的操作。...箭头函数 这个一笔带过: 箭头函数中的 this 指向是固定不变的,即是在定义函数时的指向 而普通函数中的 this 指向时变化的,即是在使用函数时的指向 class 继承 Class 可以通过 extends...子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工。
特点: JavaScript 对象是通过引用来传递的,创建的每个新对象实体中并没有一份属于自己的原型副本。当修改原型时,与之相关的对象也会继承这一改变。 JavaScript 类数组对象的定义?...方法1:当页面的元素数小于x时,则认为页面白屏。比如“没有任何内容”,可以获取页面的DOM节点数,判断DOM节点数少于某个阈值X,则认为白屏。 方法2:当页面出现业务定义的错误码时,则认为是白屏。...方法3:当页面出现业务定义的特征值时,则认为是白屏。比如“数据加载中”。说一下SPA单页面有什么优缺点?...然后当浏览器在解析到 script 标签时,会暂停构建 DOM,完成后才会从暂停的地方重新开始。...get操作,第一步时检查对象本身是否有这个属性,如果有就使用它,没有就去原型中查找。
0 } } Track Track这个函数常出现在reactive的getter函数中,用于依赖收集 源码详解见注释 function track(target: object, type: TrackOpTypes...depsMap) { targetMap.set(target, (depsMap = new Map())) } // dep用来收集依赖函数,当监听的key值发生变化,触发dep中的依赖函数更新...总结来说 在getter时进行依赖收集 在setter时触发依赖更新 function reactive(target:object){ return new Proxy(target,{...Vue3中出现了effect,重新实现了Computed属性 effect可以被理解为副作用函数,被当做依赖收集,在响应式数据更新后被触发。...Vuex4原理探究 去除冗余代码看本质 createStore 从createStore开始看起 可以发现Vuex4中的state是通过reactive API去创建的响应式数据,Vuex3中是通过new
在if条件中通过判断年级是否等于-1 来做一下操作。我们在写这段代码的时候想的可能是:当mUser不为null,而且年级不是-1的时候,通过条件判断,然后做一下操作。...但是在kotlin中,当mUser为null时,mUser?.grade的取值为null,而null != -1 ,在kotlin是成立的,这就不符合我们实际逻辑了。 解决方法如下:通过 ?...String 2、TODO 语句报错问题 在kotlin开发中,当实现某个抽象方法时,会自动生成一条TODO语句。...特别是在多线程开发环境中,而java代码又缺少了对null的强检查,这就更容易会出现空异常了。下面给大家减少及个避免 !!...原因是:Person在被转Java代码时,只会生成一个包含两个参数的构造方法,没有提供默认的构造方法。Gson在通过反射创建对象时,会优先尝试获取无参构造函数。
) { // 触发属性访问器时 console.log(`Trigger getter(${target.name}/${propertyKey})`) } class Person {...参数修饰器会为参数声明之前,同样具有三个参数: 当参数修饰器修饰的所在方法为类的构造函数/静态方法时,第一个参数表示类的构造函数(类本身)。...反之,当参数修饰器修饰的参数所在的方法为实例方法时,此时第一个参数代表类的原型。 如果修饰的为类的静态/实例方法时,第二个参数为当前参数修饰器所在方法的方法名。...target: es5 后,我们一起来看看上边的 ts 代码经过编译后的 js 代码会变成什么样子: var __decorate = function (decorators, target, key...截止目前 Typescript 中我们将装饰器编译称为 Es5 代码后的实现已经完全和大家讲解完毕,有兴趣的同学可以私下自己尝试去阅读一下编译后的 Es5 代码,其实实现的机制无非是通过不同参数个数来确定而已并没有多少复杂
其实默认Vue在初始化数据时,会给data中的属性使用Object.defineProperty重新定义所有属性,当页面取到对应属性时。...在get中通过dep.depend()收集依赖。当数据改变时,拦截属性的更新操作,通过set中的dep.notify()通知相关依赖进行更新。 Vue 中是如何检测数组变化?...指向了自己定义的数组原型方法,这样当调用数组 api 时,就可以通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次进行观测。 这里用一张流程图来说明: ?...发现没有 cb 而有 _resolve 时就会执行之前返回的 Promise 对象的 resolve 函数。...== 'production' && getter == null) { warn( `Getter is missing for computed property "${
getter,所以当访问 foo2 时,会访问自定义的 getter,因此输出 2 次 “Calculating……” val foo1 = run { println("Calculating the...getter 会 override 父类的 getter 当新建一个子类的时候,首先调用了父类的构造器,父类的 foo 为 1,并且拥有一个返回了(父类的)foo 的 getter,然后调用 init...data 修饰时,会自动实现一个比较域成员的 equals,于是就会得到 true Kotlin 只会使用主构造器中的属性来实现 equals,不会使用类在其他部分定义的变量 当明确知道自己的类考虑了所有考虑的情况时...当只使用 Kotlin(而不需要从字节码层面被 Java 使用)时,那么没有理由使用 Array,应该始终使用 List Nothing 是 Kotlin 中的底层类型,Nothing 可以看做是任何类型的子类...println(description.length) // NullPointerException 这样会使得 Kotlin 中的 Nullable 检查毫无用处,因为依然可能出现 Null Pointer