javascript 将 call 函数赋值给变量后调用报错?

无意间写到了些javascript代码,遇到了不明白的地方,求解释:

 var a = [2,3,3,1,7,5];
 var b = [2,3,3,1,7,5];
 var fn = Array.prototype.sort;
  fn.call(a);

这里可以成功处理数组a;
但是,如果这样用:

var fn1 = Array.prototype.sort.call;
fn1(b);

这里就报错了。
请输入图片描述

undefined is not a function指的是什么?

fn1 //可以输出 function call(){[native code]}

阅读 5.2k
1 个回答

我写一下Function.prototype.call的伪代码好了

Function.prototype.call = function(newThis) {
  var targetFn = this;//注意这里,call的目标函数是通过this拿到的
  var args = Array.prototype.slice.call(arguments, 1);

  return targetFn.[[Call]] (this = newTHis, arguments = args);//[[Call]]是function的内部方法
}

题主做了fn = xxx.call之后(其实原型链结算后等价于fn = Function.prototype.call),call内部拿到的所谓“targetFn”相当于丢失了。也就是fn虽然存在,但执行进入fn的"Native Code"中的时候拿不到要实际执行的函数了,参考ECMA规范中Function.prototype.call的第一步

If IsCallable(func) is false, then throw a TypeError exception.

所以这个错误抛出是符合规范的


我再写几个例子看看能不能加深一下理解。其实这事的本质就是Function.prototype.call本身也是一个function,得按照javascript的function的所有规矩来办

function foo(a) {
  console.log('bar!', this, a);
}

function baz(b) {
  console.log('bla bla', this, b);
}

var fn = baz.call;
fn.call(foo, {c:1}, 1);//bar! {c: 1} 1 

baz.call.call(foo, {c:1}, 1);//bar! {c: 1} 1 

var fn2 = baz.call.bind(foo);
fn2({c:1}, 1);//bar! {c: 1} 1 
推荐问题
logo
101 新手上路
子站问答
访问
宣传栏