Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
指「;这";在javascript中的父闭包中_Javascript_Closures_This - Fatal编程技术网

指「;这";在javascript中的父闭包中

指「;这";在javascript中的父闭包中,javascript,closures,this,Javascript,Closures,This,我想用Javascript实现这一点: function Z( f ) { f(); } function A() { this.b = function() { Z( function () { this.c() } ); } this.c = function() { alert('hello world!'); } } var foo = new A(); foo.b(); 可以通过以下方式实现: function Z( f ) {

我想用Javascript实现这一点:

function Z( f )
{
  f();
}

function A()
{
  this.b = function()
  {
    Z( function () { this.c() } );
  }

  this.c = function()
  {
    alert('hello world!');
  }
}

var foo = new A();
foo.b();
可以通过以下方式实现:

function Z( f )
{
  f();
}

function A()
{
  var self = this;
  this.b = function()
  {
    Z( function () { self.c() } );
  }

  this.c = function()
  {
    alert('hello world!');
  }
}

var foo = new A();
foo.b();

有更好的方法吗?

保留对父级的引用(如您所拥有的)是一个很好的方法,但是对于您的特定示例,不需要匿名包装器,您可以直接传递函数,如下所示:

var self = this;
this.b = function()
{
  Z(self.c);
}
this.b = function()
{
  Z(this.c);
}
/** class Delegate **/
var Delegate = function(thisRef, funcRef, argsArray) {
    this.thisRef=thisRef;
    this.funcRef=funcRef;
    this.argsArray=argsArray;
}
Delegate.prototype.invoke = function() {
    this.funcRef.apply(this.thisRef, this.argsArray);
}
/** static function Delegate.create - convenience function **/
Delegate.create = function(thisRef, funcRef, argsArray) {
    var d = new Delegate(thisRef, funcRef, argsArray);
    return function() {  d.invoke(); }
}
this.b = function() {
  Z( Delegate.create(this, this.c) );
}
,没有这个包装器,实际上不需要使用
self
变量,您可以直接使用
this
,如下所示:

var self = this;
this.b = function()
{
  Z(self.c);
}
this.b = function()
{
  Z(this.c);
}
/** class Delegate **/
var Delegate = function(thisRef, funcRef, argsArray) {
    this.thisRef=thisRef;
    this.funcRef=funcRef;
    this.argsArray=argsArray;
}
Delegate.prototype.invoke = function() {
    this.funcRef.apply(this.thisRef, this.argsArray);
}
/** static function Delegate.create - convenience function **/
Delegate.create = function(thisRef, funcRef, argsArray) {
    var d = new Delegate(thisRef, funcRef, argsArray);
    return function() {  d.invoke(); }
}
this.b = function() {
  Z( Delegate.create(this, this.c) );
}


由于下面的注释中似乎有一些混淆,上面的代码为问题保留了
this
,如果您还想在回调中保留
this
/上下文,请使用:

对于
Z

function Z( f )
{
  f.call(this);
}

.

有一种模式通常被称为“委托”,它解决了这个问题

在javascript中,一个不太花哨的实现可能如下所示:

var self = this;
this.b = function()
{
  Z(self.c);
}
this.b = function()
{
  Z(this.c);
}
/** class Delegate **/
var Delegate = function(thisRef, funcRef, argsArray) {
    this.thisRef=thisRef;
    this.funcRef=funcRef;
    this.argsArray=argsArray;
}
Delegate.prototype.invoke = function() {
    this.funcRef.apply(this.thisRef, this.argsArray);
}
/** static function Delegate.create - convenience function **/
Delegate.create = function(thisRef, funcRef, argsArray) {
    var d = new Delegate(thisRef, funcRef, argsArray);
    return function() {  d.invoke(); }
}
this.b = function() {
  Z( Delegate.create(this, this.c) );
}
在您的示例中,您可以这样使用它:

var self = this;
this.b = function()
{
  Z(self.c);
}
this.b = function()
{
  Z(this.c);
}
/** class Delegate **/
var Delegate = function(thisRef, funcRef, argsArray) {
    this.thisRef=thisRef;
    this.funcRef=funcRef;
    this.argsArray=argsArray;
}
Delegate.prototype.invoke = function() {
    this.funcRef.apply(this.thisRef, this.argsArray);
}
/** static function Delegate.create - convenience function **/
Delegate.create = function(thisRef, funcRef, argsArray) {
    var d = new Delegate(thisRef, funcRef, argsArray);
    return function() {  d.invoke(); }
}
this.b = function() {
  Z( Delegate.create(this, this.c) );
}
您还可以编写期望接收委托的函数:

function Z( d ) {
    d.invoke();
}
然后,在
A
中,您的
b
的impl变为:

this.b = function() {
    var d = new Delegate(this, this.c);

    Z( d );
    SomeOtherFunc( d );
}

委托
只是提供了一种简单、一致的方法,将
这个
引用(您称之为
self
)封装在一个对象实例中,该对象实例可以像任何其他对象实例一样处理。它更具可读性,并且可以避免使用诸如
self
之类的多余变量污染函数范围。更奇特的委托实现可以有自己的方法和其他相关状态。还可以以有助于最小化某些与作用域相关的内存管理问题的方式构建委托(尽管我在这里展示的代码肯定不是这样的示例)。

您也可以使用

this.b = function()
{
    Z( (function () { this.c() }).apply(this) );
}

对,在这个简单的例子中,没有理由使用包装器。在必要的地方,不难想出一个例子。(更改参数等)但是,如果您不包装,我假设闭包是按预期传递的?如果没有匿名包装,则调用
c
时使用了错误的
this
引用。@Jonathan-是的,正确,在这种情况下,您可能希望传递一个变量,就像您有
self
一样,让您访问闭包中的内容。@Lee-事实并非如此,演示显示了这一点,使用包装器
这是一个不正确的引用。@Nick-function
c
是类
a
的成员。它应该能够在内部使用
来访问
A
的其他成员。当通过
Z
调用而不使用包装器时,情况并非如此。您可以看到这一点,我认为这是行不通的:
Z(function(){Delegate.create(this,c)})。没有包装器,就不需要
self
,也不需要委托,因为写
Z(this.c)比较短
@Jonathan-您添加了一个额外的包装器,这在我的示例中不存在。只是
Z(Delegate.create(this,c))
;我对委托示例进行了一些扩展,使其更灵活、更清晰。@Jonathan-
Z(this.c)
将起作用,只要您不关心在
c
内部运行时,this
引用了什么对象。您显示的代码没有在
c
中使用
this
,因此不会出现任何问题。如果您签出(这是@Nick示例的轻微修改)[,您将看到潜在的问题,该问题在原始示例中由匿名包装器解决,或者使用更正式的构造(如委托)。任何一个都可以。如果您必须在回调中调用
.invoke()
,为什么不使用
.call()
.apply()
在两个位置?这是一种更简单的方法。@尼克-你不必调用
invoke()
在您的回调中。这是我展示的两个示例之一。第一个示例是这种方法最常见的用法:静态
委托。create
返回一个简单的函数。您可以将它传递到任何可以传递任何其他函数的地方。第二个示例仅显示了一种替代用法,这实际上是o仅当您扩展委托以包括其他特定于域的特性时才有用——在某些情况下,这可能是一个非常理想的特性。