JS中何时需用call/apply绑定this?含Mongoose及Express相关疑问
错误原因
你遇到的报错本质就是this指向丢失,和你参考的资料里描述的场景完全一致。
当你把Cars.find作为参数单独传给print函数时,这个方法已经和Cars模型对象脱离了绑定关系。JS中普通函数的this是调用时动态决定的,如果你直接调用func(param1),此时func运行时的this在非严格模式下是全局对象,严格模式下是undefined,根本不是Mongoose要求的模型对象,所以会抛出Model.find() cannot run without a model as this的错误。
你用func.call(Cars, param1)的写法是正确的,相当于手动把func运行时的this绑定为Cars模型,满足Mongoose的调用要求。
call/apply的使用场景
通用JS场景
当你需要临时修改某个函数运行时的this指向时,就可以使用call/apply,常见场景包括:
- 将对象的方法剥离出来单独调用,需要重新绑定原对象作为运行时
this,和你当前的场景一致 - 借用其他对象的内置方法,比如用
Array.prototype.slice.call(arguments)把类数组对象转为普通数组 - 实现类继承,在子类构造函数中用
Parent.call(this, 初始化参数)调用父类构造函数完成实例初始化
Mongoose专属场景
Mongoose的所有模型静态方法、实例方法都强依赖this指向对应的模型/实例对象,只要你把这些方法从原对象上剥离出来单独传递、调用,就必须手动用call/apply绑定this为对应的模型/实例,否则都会抛出类似的上下文缺失错误。
Express的next()说明
next是Express内置的中间件调度函数,属于框架内置功能,不是用户可自定义的回调:
- 调用
next()时,会直接进入下一个匹配的普通中间件/路由处理函数 - 调用
next(err)时,Express会跳过所有后续普通中间件,直接进入错误处理中间件栈,就是你观察到的“跳过”效果
你可以自定义错误处理中间件接收next(err)传递的错误参数,但next本身的调度逻辑是Express内置实现的,无法直接修改。
内容的提问来源于stack exchange,提问作者okzoomer
相关产品推荐
相关产品推荐

