【问题标题】:Javascript "this" in static methods静态方法中的 Javascript“this”
【发布时间】:2012-06-30 05:34:57
【问题描述】:

我有这样的代码:

User = function(){}

User.a = function(){
  return "try";    
}

User.b = function(){

}

​ 从 User.b() 我可以调用 User.a() 使用:

User.b = function(){
    return User.a();
    }

但不使用它,因为它不是用户的实例(User.a() 和 User.b() 类似于“静态方法”)。

我想要做的是能够从 User.b() 调用 User.a() 而不知道哪个是主要功能,在这种情况下是 User。

这样的东西可以用在静态方法中。

【问题讨论】:

    标签: javascript oop class static-methods


    【解决方案1】:

    实际上,js 中没有方法或静态方法,只有分配给对象属性的函数(函数也是对象),它们都以相同的方式工作。由于您将其称为 User.b(),因此 this 将是 User 进行呼叫。

    User.b = function() {
        return this.a();
    }
    

    【讨论】:

    • 当您说 Javascript 没有方法时,您对“方法”与“功能”的定义是什么?你会得到一个神奇的额外参数,它的值取决于你用来调用函数的对象,这看起来非常像方法。如果您对“方法”的定义需要存在类,那么我认为您的定义可能过于狭窄。如果还有别的东西,我很好奇它是什么。谢谢。
    • @MarkReed 函数与任何东西都没有关联,你可以像var a = User.b 一样存储函数User.b,当你调用a() 时它会改变一切。看到这一点的一种常见方法是添加像elem.addEventListener( "click", this.clicked, false ) 这样的事件侦听器,这可以通过使用ugly hacks 来解决,尽管许多只是在这一点上放弃 oop 并使用内联闭包。我的观点是this.clickedthis 根本没有关联,它只是一个愚蠢的函数引用。
    • 我不同意。 JavaScript 中的方法不像函数那样是一等对象,但这不等于说它们不存在。否则,C++、Java、Python 和许多其他面向对象的语言也没有方法。
    • 如果你想继续,我们应该拿这个来聊天。但很快:根据您的 addEventListener 示例,您对 JS 没有方法的论点是函数值不封装它们的调用者。我认为它表明虽然 JS 具有一流的函数(您可以传递函数值),但它没有一流的方法(这些值不包括调用者)。所以我会买那些方法在 JS 中不是一流的。但我不相信它们不存在,因为this 的神奇设置没有它们就没有意义。
    • @MarkReed this 在每个函数调用中都设置了,这是否会生成所有函数方法? specification 将方法定义为method - function that is the value of a property。所以实际上(我最初声称的),它只是一个函数。当然,您可以将它们称为方法、静态方法、类等,但只有当观众真正理解时才有效。如果 OP 理解它只是附加到属性的函数而不是静态方法,他可能一开始就不会提出问题。
    【解决方案2】:

    您在 javascript 中没有正常的继承。我猜你正在尝试做这样的事情:

    User = function(){
        this.a= function(){
             return 'try';
        }
        this.b= function(){
            return this.a();
        }
    }
    

    这样 User 就变成了一个构造函数。每个新的 User 实例都可以访问这些方法。所以如果你想创建一个 User 类的新实例,你可以使用 new 关键字:

    var client= new User()
    

    然后您将可以使用客户端访问用户的所有方法

    client.b() //returns 'try'
    

    【讨论】:

    • a() ... 这会给你ReferenceError。你是说this.a()
    【解决方案3】:

    嗯,函数独立于它们的容器对象而存在;他们只是价值观。所以如果你没有将它们作为对象上的方法调用,它们会继承调用上下文中this 的任何内容。在这种情况下,期望他们知道他们的容器与将值 1 分配给 User.x 然后期望数字 1 以某种方式知道 User 是一样的。

    但是,当您调用User.a()User.b() 时,您实际上将它们称为方法-(函数对象)User 的方法。所以this 将与User 相同,而b 可以调用this.a(),你应该很高兴。

    【讨论】:

      【解决方案4】:

      唯一决定函数上下文的是你如何调用它。

      如果您使用普通标识符(函数名、变量或属性)调用它,则上下文将是全局 window 对象:

      someFunction();
      

      如果您使用句点调用它来访问对象成员,则上下文将是对象:

      someObject.someFunction();
      

      如果将一个成员从一个对象复制到一个变量中,则与该对象不再有任何联系,它将以window作为上下文调用:

      var x = someObject.someFunction;
      x();
      

      如果将函数作为属性分配给对象,并使用该对象调用它,则上下文将是该对象:

      someObject.x = someFunction;
      someObject.x();
      

      对于您的具体情况,User 是一个函数,也是一个对象。

      如果您使用User.b 调用该函数,它的上下文将是User 对象,在这种情况下恰好是一个函数。在函数中,您仍然可以使用 this 访问上下文:

      User.b = function(){
        return this.a();
      }
      

      【讨论】:

      • 我觉得值得一提的是句号不是重要的部分,因为foo.bar只是foo['bar']的糖。当您从容器中检索函数对象并调用它时,this 被设置为容器:SomeObject.someFunction() - this 设置为 SomeObjectSomeObject['someFunction']() - 一样; (SomeObject.someFunction)() - 相同(!); (f = SomeObject.someFunction)() - this 设置为全局对象。
      猜你喜欢
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多