为什么“this”指的是全局对象
Why does `this` refer to the global object?
我有一个Backbone Marionette应用程序,其模块定义如下。当我运行这个应用程序时,控制台日志语句会打印出@
作为窗口对象。当运行list
方法时,我认为this
(@
)将引用List.Controller
对象。我错过了什么?
###
The Header list controller.
###
define [
'cs!app',
'cs!./view',
'cs!modules/header/entities'
], (
App,
View
) ->
App.module 'Header.List', (List, App, Backbone, Marionette, $, _) ->
List.Controller =
list: ->
console.log(@)
headers = App.request 'header:entities'
view = new View.Headers {collection: headers}
App.headerRegion.show view
setActiveHeader: (headerUrl) ->
headers = App.request 'header:entities'
header = headers.find (header) -> (header.get 'url') == headerUrl
header.select()
headers.trigger 'reset'
App.commands.setHandler 'header:setActive', (headerUrl) ->
List.Controller.setActiveHeader headerUrl
App.Header.List.Controller
更新
这是调用列表方法的模块:
###
The Header module.
###
define [
'cs!app',
'cs!./list/controller'
], (
App,
listController
) ->
App.module 'Header', (Module, App, Backbone, Marionette, $, _) ->
Module.startWithParent = false
App.module 'Routers.Header', (ModuleRouter, App, Backbone, Marionette, $, _) ->
class ModuleRouter.Router extends Marionette.AppRouter
appRoutes: {}
executeAction = (action, args) ->
action(args)
API =
list: ->
executeAction listController.list
App.Header.on 'start', ->
API.list()
App.addInitializer ->
new ModuleRouter.Router {listController: API}
App.Header
问题是使用window
(全局)上下文调用对象listController
的方法list
。
之所以发生这种情况,是因为您以这种方式调用方法:executeAction listController.list
,而从executeAction
调用方法只是以正常方式:action(args)
您可以将方法绑定到类(使用_.bind
),也可以使用js Function
的call
或apply
方法(绑定方式更容易):
绑定(_.bind(action, context)
:
executeAction _.bind(listController.list, listController)
使用另一上下文(method.call(context, arg1, ..)
或method.apply(context, argsArray)
)调用(或应用)
executeAction = (context,action, args) ->
action.call(context, args)
API =
list: ->
executeAction listController, listController.list
您应该在初始化函数中使用_.bindAll(this)
,只需添加:
initialize:->
_.bindAll(this, "list") // Like @mu mentioned in the comment, function name is required
编辑:
尽管@KiT-O是正确的,并且调用者可以使用_.bind
函数将函数绑定到Controller。这不应该是调用者的责任,函数需要绑定到其正确的上下文,调用者不应该关心/知道它
这就是为什么我更喜欢_.bindAll
解决方案,尽管它为Backbone 添加了更多的样板代码
this
在函数被调用之前不会被绑定,并且取决于函数的调用方式。您可以将其视为隐式传递给函数的一个额外参数。
在这种情况下,我认为您正在使用controller()
调用您的函数。通过调用函数作为方法(如foo.bar()
或foo["bar"]()
)或通过call()
或apply()
显式设置this
值。您的调用既不执行也不执行,因此这将恢复为全局对象。
从这里开始。
- 全局变量和全局对象的属性之间有什么区别吗
- javascript无法重新定义函数内部的全局对象
- Javascript,从静态函数中打印全局对象
- 为什么“this”指的是全局对象
- Do let语句在全局对象上创建属性
- underscore.js,名为“”的全局对象;出口;和livefyre javascript API-集成冲突
- 为什么“this”指的是对象“obj”而不是全局对象
- 从函数调用全局对象的方法
- 谷歌分析的全局对象
- AngularJS:避免使用“angular”全局对象
- Javascript Web Worker 修改全局对象
- 想要在回调中更新对象,给出正确的日志,但全局对象未更新
- 让函数中的接收器默认为全局对象背后的基本原理是什么?
- 蜘蛛猴:如何删除全局对象
- 为什么函数在全局对象中不可用
- 访问请求会在全局对象中生成
- 全局对象问题
- React Native 中全局对象的模式
- Expressjs - 全局对象
- 是否可以在 Javascript 中更改或删除全局对象的属性