Javascript 嵌套。绑定未按预期工作

Javascript 嵌套。绑定未按预期工作,javascript,closures,call,bind,nested-function,Javascript,Closures,Call,Bind,Nested Function,不幸的是,.bind在创建更复杂的闭包时让我很难过 我对其中的原因很感兴趣。一旦嵌套函数,绑定的工作方式似乎就不同了 例如: function t(){ t = t.bind({}); //correctly assigns *this* to t function nested_t(){ nested_t = nested_t.bind({}); // fails to assign *this* to nested_t return nes

不幸的是,
.bind
在创建更复杂的闭包时让我很难过

我对其中的原因很感兴趣。一旦嵌套函数,绑定的工作方式似乎就不同了

例如:

function t(){
    t = t.bind({}); //correctly assigns *this* to t  
    function nested_t(){
        nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
        return nested_t; 
    }
    return nested_t(); 
}
//CASE ONE
alert(t()); 
          // alerts the whole function t instead of nested_t

//CASE TWO
aleft(t.call(t)); 
         // alerts the global object (window) 
在这两种情况下,我都希望出现这样的行为:

function t(){
    var nested_t = function nested_t(){
        return this;
    };
    return nested_t.call(nested_t);
}

alert(t.call(t));

如果有人能在第一种(和/或)第二种情况下解释
.bind
的行为,我们将不胜感激

因此,我在这里并不是完全重复您的问题(两种情况都返回全局对象),但我将尝试解释我看到的代码

function t(){
    t = t.bind({}); //correctly assigns *this* to t  
    function nested_t(){
        nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
        return this; 
    }
    return nested_t(); 
}
//CASE ONE
alert(t()); 
让我们一步一步来

首先,定义函数
t()
。然后,在调用时,它会被一个干净的上下文覆盖。然而,我看不到这个上下文的任何用法

现在,定义了一个嵌套函数(
nested\t
)。调用时,它会被干净的上下文覆盖。然后返回调用它时的上下文

返回到
t()
。然后返回
nested_t()
,而不是
nested_t
本身的结果。在原始函数调用中,
nested\u t
仍在使用全局上下文调用


因此,当您运行
t()
时,它将返回全局对象。

因此,我并不是在这里完全重复您的问题(两种情况都返回全局对象),但我将尝试解释我看到的代码

function t(){
    t = t.bind({}); //correctly assigns *this* to t  
    function nested_t(){
        nested_t = nested_t.bind({}); // fails to assign *this* to nested_t
        return this; 
    }
    return nested_t(); 
}
//CASE ONE
alert(t()); 
让我们一步一步来

首先,定义函数
t()
。然后,在调用时,它会被一个干净的上下文覆盖。然而,我看不到这个上下文的任何用法

现在,定义了一个嵌套函数(
nested\t
)。调用时,它会被干净的上下文覆盖。然后返回调用它时的上下文

返回到
t()
。然后返回
nested_t()
,而不是
nested_t
本身的结果。在原始函数调用中,
nested\u t
仍在使用全局上下文调用

因此,当您运行
t()
时,它将返回全局对象。

您的代码是如何工作的 现在还不清楚你的代码在做什么。您可以找到
.bind()
的文档。看起来您可能不知何故误解了此是什么以及如何使用它。无论如何,运行代码时会发生以下情况:

  • 在全局范围内创建
    t
    函数
  • [案例一]调用
    t
    函数。
  • 全局范围
    t
    被替换为新值(原始
    t
    绑定到特定上下文-匿名空对象),该值不会以任何方式影响当前调用。此外,当全局
    t
    被覆盖时,本地
    t
    表现为只读。您可以通过尝试以下代码来检查它:
    (函数foo(){return(函数栏(){bar=window.bar='baz';返回栏;}();})(
    )并将返回值与
    window.bar
    进行比较
  • 在嵌套上下文(而不是全局上下文)中的
    嵌套\u t
    也会发生同样的情况
  • 返回嵌套调用的结果
    nested_t
    返回调用它时使用的上下文,即
    窗口
    ,因为没有指定上下文。具体来说,它不是用空对象上下文调用的,因为内部的
    .bind()
    不会影响调用本身
  • [案例二]同样的事情再次发生。现在您只需调用
    t
    ,将其本身作为上下文。由于
    t
    在其代码中的任何地方都不使用上下文(
    this
    ),因此实际上没有任何变化

  • 你的误解是什么 基本上,你混淆了两件事——函数实例和函数调用上下文。函数在JavaScript中是“一等公民”——它是一个对象,您可以为其属性赋值

    function foo () {
        foo.property = 'value';
    }
    foo();    // foo.property is assigned a value
    
    这与函数调用上下文无关。调用函数时,会为该调用指定一个上下文,可以使用
    (函数体内部)访问该上下文

    使用
    .bind()
    时,只需使用相同的代码创建一个新函数,该函数锁定到特定上下文

    function foo () {
        this.property = 'value';
    }
    var fixedContext = {},
        object = {};
    bar = foo.bind(fixedContext);
    foo.call(object);    // fixedContext.property is set instead of object.property
    
    但在这种情况下,也有函数实例
    foo
    bar
    ,它们也可以被分配属性,与这些函数的调用上下文无关。

    代码的工作方式 现在还不清楚你的代码在做什么。您可以找到
    .bind()
    的文档。看起来您可能不知何故误解了此
    是什么以及如何使用它。无论如何,运行代码时会发生以下情况:

  • 在全局范围内创建
    t
    函数
  • [案例一]调用
    t
    函数。
  • 全局范围
    t
    被替换为新值(原始
    t
    绑定到特定上下文-匿名空对象),该值不会以任何方式影响当前调用。此外,当全局
    t
    被覆盖时,本地
    t
    表现为只读。您可以通过尝试以下代码来检查它:
    (函数foo(){return(函数栏(){bar=window.bar='baz';返回栏;}();})(
    )并将返回值与
    window.bar
    进行比较
  • 在嵌套上下文(而不是全局上下文)中的
    嵌套\u t
    也会发生同样的情况
  • 返回嵌套调用的结果
    nested_t
    返回调用它时使用的上下文,即
    窗口
    ,因为没有指定上下文。具体来说,它不是用空对象上下文调用的,因为内部的
    .bind()
    不会影响调用本身
  • [案例二]同样的事情再次发生。现在您只需调用
    t
    ,其本身就是
    var foo = function() { return this.x; };
    alert(foo());  // undefined
    alert(foo.bind({x: 42})()); // 42
    
    var bar = function() { return foo.bind(this)(); };
    alert(bar());  // undefined
    alert(bar.bind({x: 42})());