为什么这个函数表达式未定义?

Why is this function expression undefined?

有人能解释一下为什么当我将它存储在变量中时这个函数会变成未定义的吗?

model.where({'artisan.id':id}).count(function(err, doc) {
  console.log(err, doc); // this work
})

var fn = model.where({'artisan.id':id}).count;

console.log(typeof fn); // ==> 'function'

fn(function(err, doc) { // undefined is not a function
      console.log(err, doc); 
})

谢谢。

我认为错误不是从您所说的行中抛出的,而是从 fn 函数内部抛出的,因为您正在使用错误的上下文执行它。

当你说 model.where(...).count(...) 时,计数函数是使用从 where() 返回的值作为其上下文执行的,但是当你 fn(...) 没有发生时,函数将被执行使用 window 上下文(undefined 在严格模式下)它可能找不到一些必需的内部属性导致错误

var where  = model.where({
    'artisan.id': id
});

var fn = where.count;

console.log(typeof fn); // ==> 'function'

fn.call(where, function (err, doc) { // undefined is not a function
    console.log(err, doc);
})
//or
where.count(function (err, doc) {
    console.log(err, doc); // this work
})

该错误可能是因为您实际上并未将 count() 作为方法调用。

.count 分配给 fn 仅保留对 function 本身的引用。它与 model.where({'artisan.id':id}) 查询对象分离,稍后使用默认 this 值调用 - globalundefined,具体取决于严格模式的使用。

在某些时候,它可能会尝试引用另一种方法,该方法将无法通过默认 this 获得,例如:

function count(callback) {
    this.method(...);      // TypeError: undefined is not a function
    // global.method(...);
}

解决此问题的一种方法是 .bind() 方法,因此它的 this 值是固定的:

var query = model.where({'artisan.id':id});
var fn = query.count.bind(query);

fn(function (...) { ... });