【问题标题】:Confused about execution context in JS对 JS 中的执行上下文感到困惑
【发布时间】:2017-08-16 00:01:58
【问题描述】:
// 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对象。

第二个困惑点是argumentsargument for apply() 到底是从哪里来的?是的,我知道它是在每次函数调用时生成的用于访问函数参数的对象 - 但这一行位于没有任何参数的匿名函数内部。我没有任何线索,感谢任何提示。

提前谢谢你!

【问题讨论】:

  • @dayuloli 本地执行上下文是什么?再次引用我的书“函数是使用定义时有效的作用域链执行的。”,这是否意味着执行上下文是匿名函数之一?
  • 如果执行上下文是任意函数的上下文,这是否意味着arguments 对象为空(因为该函数不接受任何参数)?那有什么意义呢?我不想使用原始函数会收到的参数吗?
  • "thisarg是this,也就是说执行上下文保持不变:original对象" - 不,original是函数(方法)应该被调用的引用,它不是上下文。而且您也不知道this 上下文是否是o(方法被覆盖的对象)——它可以是任何东西。因此,我们使用this
  • "arguments 对象在每次函数调用时生成,用于访问函数参数 - 但此行位于没有任何参数的匿名函数内" - 否,匿名函数没有声明任何参数。这并不意味着它不能被任意多个参数调用。
  • @FlorianWicher local execution context 表示调用方法的位置,即如果m 被调用为函数this 是全局的,如果m 被调用为methodobject , thisobject ,如果 m 在另一个函数中被调用 this 也指全局

标签: javascript apply execution scoping


【解决方案1】:

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

如果你直接在匿名函数中调用originaloriginal里面的this肯定会引用global(在严格模式下是undefined)。另一方面,匿名函数被声明为o的方法,所以如果你调用为o.m(),匿名函数内部的this应该引用o。需要将o 传递给original,因为它保留了语义。

除了绑定thisapply 还可以将参数数组转换为单个参数。

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 时被赋值,它是动态的。

【讨论】:

    最近更新 更多