对JS中的执行上下文感到困惑

时间:2017-08-16 00:01:58

标签: javascript apply execution scoping

// Replace the method named m of the object o with a version that logs
// messages before and after invoking the original method.
function trace(o, m) {

  // Remember original method in the closure
  var original = o[m];

  // Define the new method
  o[m] = function() { 

    // Log message
    console.log(new Date(), "Entering:", m);

     // Invoke original
    var result = original.apply(this, arguments);

     // Log message
    console.log(new Date(), "Exiting:", m);

    return result;
  };
}

您好!上面给出的代码示例来自我的编码书。它试图用JavaScript中的apply函数来说明一种称为“猴子修补”的实践。我真的很困惑调用原始函数的行的性质:

var result = original.apply(this, arguments); // Invoke original.

据我所知,原始函数的调用也可以在apply()的帮助下编写,因为thisarg是this,也就是说执行上下文保持不变: original对象。

第二点混淆是arguments的{​​{1}}论证来自哪里?是的,我知道它是在每个函数调用中生成的对象,用于访问函数参数 - 但是这一行是在没有任何参数的匿名函数内部。我没有任何线索,我很感激任何提示。

提前谢谢!

1 个答案:

答案 0 :(得分:2)

您的第一个问题:为什么需要apply

如果您直接在匿名函数中调用originalthis内的original肯定会在严格模式下引用globalundefined)。另一方面,匿名函数被声明为o的方法,因此如果您调用o.m(),匿名函数内的this应引用o。需要将o传递给original,因为它保留了语义。

除了绑定this之外,apply还可以将参数数组转换为单个参数。

function toBeCalled(x,y){
    console.log('x is: '+x+" y is:"+y)
}

function x (){
    toBeCalled(arguments)
    toBeCalled.apply(this,arguments)
}

x('aa','bb','vv')

//x is: [object Arguments] y is:undefined
//x is: aa y is:bb

看到区别?

第二个问题:arguments来自哪里?

在JavaScript中,arguments是函数范围内的内置变量。 arguments的值只能在调用函数时确定 ,它根本不固定。

function x (){
    console.log(arguments)
}

x('aa','bb','vv')
x("ff","dd")
x(1123)

arguments在调用x时分配了一个值,它是动态的。